Thread类
Java多线程使用Thread类实现,该类实现了接口Runnable。
创建线程的方法
创建线程有如下3种方法。
- 继承Thread,重写run方法。
- 实现Runnable接口,重写run方法。
- 实现Runnable接口,重写run方法。(使用lambda表达式实现)。
见如下代码:
public class Hello {
public static void main(String[] args) {
//如下是创建线程的3种方法。
Thread t1 = new myThread();
Thread t2 = new Thread(()->{
System.out.println("hello!");
});
Thread t3 = new Thread(new myRunnable());
t1.start();
t2.start();
t3.start();
}
}
class myThread extends Thread {
@Override
public void run() {
System.out.println("hello!");
}
}
class myRunnable implements Runnable {
@Override
public void run() {
System.out.println("hello!");
}
}
**注意:**启动线程是start()方法,run()并不能启动一个新的线程(run方法是执行一次run函数,并不是启动线程)。
sleep方法
执行Thread.sleep(100)
方法使当前线程暂停100毫秒。
当线程sleep时,如果被停止,则抛出InterruptedException
。
注意:当sleep时间到了以后线程进入的是就绪状态而非执行状态!
setDaemon方法设置守护线程
守护线程是为其他线程服务的,如垃圾回收线程。
特点:当一个进程里所有线程都是守护线程时,结束该进程。守护线程中产生的线程也是守护线程。
public class TestThread {
public static void main(String[] args) {
Thread t = new Thread(() -> {
System.out.println(Thread.currentThread().getName());
while (true) {
}
}, "守护线程");
t.setDaemon(true);
t.start();
System.out.println(Thread.currentThread().getName());
}
}
结果:该程序正常退出了,并没有因为while (true)
卡死。
join方法
主线程:所有进程,至少会有一个线程即主线程,即main方法开始执行,就会有一个看不见的主线程存在。
调用join()
方法主线程会等待该线程结束完毕, 才会往下运行。
public class TestThread {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程睡眠结束!");
});
Thread t2 = new Thread(() -> {
System.out.println("t2运行了");
});
t.start();
//t.join();
t2.start();
}
}
运行结果:可以看到,当t.join()
没有被注释时,会等待10秒以后才会输出"2运行了!
setPriority方法设置线程优先级
线程的优先级可以通过setPriority(int newPriority)
方法设置。线程优先级高仅仅表示线程获取的CPU时间片的几率高,但这不是一个确定的因素!
通过源码可以看到优先级的范围是1~10,默认优先级是5.
yield临时暂停
Thread.yield()
方法可以暂停当前线程,让其他线程先执行。
interrupt请求终止线程
使用interrupt来请求终线程,要注意的是:interrupt不会真正停止一个线程,它仅仅是给这个线程发了一个信号告诉它,它应该要结束了(明白这一点非常重要!)也就是说:Java设计者实际上是想线程自己来终止,通过上面的信号,就可以判断处理什么业务了。具体到底中断还是继续运行,应该由被通知的线程自己处理。
检查该线程是否被中断有两个方法:
- 静态方法interrupted()–>会清除中断标志位
- 实例方法isInterrupted()–>不会清除中断标志位
注意:如果sleep或者wait的进程被请求中断会抛出异常。
import org.omg.PortableServer.THREAD_POLICY_ID;
public class ThreadTest {
public static void main(String[] args) {
Thread t = new Thread(() -> {
int i = 0;
while (!Thread.currentThread().isInterrupted()) {
//如果当前线程没有被请求中断,则一直输出a
System.out.println(i++);
}
System.out.println(Thread.currentThread().isInterrupted());
System.out.println(Thread.interrupted());
System.out.println(Thread.currentThread().isInterrupted());
});
t.start();
new Thread(() -> {
try {
Thread.sleep(1000);
t.interrupt(); //等待1秒后请求中断t
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
输出结果:
可以看到,调用静态方法以后,标志被清楚了。