Thread 属于 java.lang包,所以可以直接用,不需要引入
- Thread 类的 sleep() 方法是一个静态方法
public static void printSlowly(String text, long interval) throws InterruptedException {
for (char ch : text.toCharArray()) {
Thread.sleep(interval);
System.out.print(ch + " ");
}
System.out.println();
}
-
线程栈
线程栈 -
代码是被线程执行的,任何代码都可以通过Thread.currentThread() 获取执行当前代码的线程
System.out.println("程序开始,执行的线程名字叫做" + Thread.currentThread().getName());
创建线程的方式
- 方式一 : 继承并实现 Runable 接口中的run()方法
public static void main(String[] args){
Thread thread = new Thread(new PrintStoryRunnable("pilibala", 300));
}
static class PrintStoryRunnable implements Runnable {
private String text;
private long interval;
public PrintStoryRunnable(String text, long interval) {
this.text = text;
this.interval = interval;
}
@Override
public void run() {
try {
double num = Math.random();
System.out.println("执行这段代码的线程名字叫做" + Thread.currentThread().getName());
printSlowly(text, interval);
System.out.println(Thread.currentThread().getName() + "执行结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
同步控制之synchronized
- synchronized 关键字用来修饰成员方法,代表这个方法对于同一个对象来说,同一时间只允许一个线程执行,别的线程如果也调用这个实例方法,就需要等待已经在执行这个方法的线程执行完毕,才能进入方法执行。
public synchronized void change(){
//balabala
}
- synchronized 代码块
就是我用 synchronized 修饰的代码块里的代码是一次只能有一个线程调用的,代码块之外的不受影响
// 只要不是 null ,任何一个对象都可以用来做锁
private Object lockObj = new Object();
synchronized (lockObj){
number += delta;
}
- synchronized 修饰静态方法 (效果等同于用synchronized 所有当前类)
public synchronized static void changedata(){
// method body
}
// synchronized 修饰静态方法的效果等同于用 synchronized 锁住当前类
// 例如当前类的类名是 DataHolder
synchronized (DataHolder.class){
// balabala
}
守护线程
- 守护线程是个好东西,比如有些程序中需要有一些辅助线程去执行一些任务,比如说程序需要做一些垃圾回收,反正就是做一些辅助任务。我们知道,Java程序入口就是启动main线程,main线程又去启动其他线程,当所有线程都运行结束时,JVM退出,进程结束,但是!这时还有一些原来作为辅助线程的线程还没退出怎么办??我JVM都退出不了🙄️~,这时我们就可以把这些作为辅助线程的线程设置为守护线程,只要程序中非守护线程执行结束,守护线程不管是不是在执行,JVM都可以退出。(守护线程工具人👹实锤
// 设置守护线程的方法就是在线程调用start() 方法前调用 setDeamon(true)
wait 和 notify 用于多线程协调运行
- 在 synchronized 内部可以调用wait()使线程进入等待状态。
- 必须在已获得锁对象上调用wait() 方法。
- 在synchronized 内部可以调用 notify() or notifyAll() 唤醒其他等待线程。
- 必须在已获得锁对象上调用notify() or notifyAll() 方法。
- 已唤醒的线程还需要重新获得锁后才能继续执行。
- wait() 方法要以 try/catch 包覆,或是掷出 InterruptedException 才行,否则编译时会报错。
使用notify() & wait()
练习题
join : Waits for this thread to die.
/**
* Waits for this thread to die.
*
* <p> An invocation of this method behaves in exactly the same
* way as the invocation
*
* <blockquote>
* {@linkplain #join(long) join}{@code (0)}
* </blockquote>
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
public final void join() throws InterruptedException {
join(0);
}
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
java.lang.Thread.join(long millis, int nanos)方法实例
ThreadLocal 是个什么东西?
- 首先我们要明白很重要的一个概念:在一个线程中,横跨若干方法调用,需要传递的对象,我们通常称之为上下文(Context)
- ThreadLocal 表示线程的局部变量。
- 使用ThreadLocal 要用try ... finally 结构,并在finally 中清除。
volatile
- 用 valatile 修饰的成员变量可以不被指令重排影响
- volatile 关键字修饰的变量在运行时会强制从主存中去取数据而不是cpu的内存
网友评论