Java多线程虽然知识点众多,但抓住了基础,也不难解决。
接着上一篇并发基础,再说一些额外的知识点。上篇文章我们说了线程的状态,还有线程的一些属性。这次我们再说一些Thread类的用法,再说下线程组的概念。
线程的操作
这里说下线程的一些其它操作。
中断
在Java中,线程中断是一种重要的线程协作机制。中断不会使程序立刻退出,而是给线程发送一个通知,告诉目标线程,有人希望你退出了。至于目标线程收到通知后如何处理,则完全由目标线程自行决定。
// 中断的方法
public static boolean Thread.interrupted() //静态方法,判断是否被中断并对中断标志位进行复位
public boolean Thread.interrupted() //判断是否被中断
public void Thread.interrupt() //中毒线程,只改变中断标志位
在线程运行的时候,若想要中断起作用,必须要判断中断标志位才行。
public class InterruptTest {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
while (true){
if (Thread.currentThread().isInterrupted()){
System.out.println("interrupted");
break;
}
try {
Thread.sleep(2000);
}catch (InterruptedException e){
System.out.println("sleep 中断异常");
// Thread.sleep由于中断抛出异常,它会清除中断标志位,所以要再中断一次。
Thread.currentThread().interrupt();
}
}
});
t1.start();
Thread.sleep(2000);
t1.interrupt();
}
}
注意: Thread.sleep()方法由于中断抛出异常,此时它会清除中断标志位,如果不加处理,下次循环开始,就无法捕捉到这个中断,因此在异常处理中,再次设置中断标志位。
yield
public static native void yield();
这是一个静态方法,一旦使用,它会使当前线程让出CPU,也就是释放当前抢占到的资源,然后再次和大家一起抢资源。
调用yield方法不代表线程把资源完全的让给其它线程了,调用的线程有可能连续多次抢到资源的。这个方法基本上很少用。
join
根据名字,加入,也就是一个线程想要加入其它的线程,想要加入的话要怎么办呢?调用join的线程会一直执行直到完成。
如果t是一个正在运行的线程对象,调用t.join()的话,当前的线程会停止执行,一直等t线程执行完毕,才会开始。
join会对interrupt做出响应,如果调用了interrupt方法,会抛出中断异常。
public class JoinTest {
public static int i = 0;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 100; j++) {
i++;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
// 如果没有调用join方法,输出的i会小于100
t.join();
System.out.println(i);
}
}
线程组
如果只有一个士兵,直接指派就好了,如果有10个士兵,最好组成一个班。如果有50个士兵,最好组成一个排。
线程组也是一样,如果有多个线程做相同的事情,最好给他们分配到某个线程组中。这样既方便阅读,也方便调试。
所有线程,默认都是放在main
线程组中的。
在创建线程的时候,可以指定线程组。
// name为线程的名称
// stackSize,创建的线程指定的栈大小
public Thread(ThreadGroup group, Runnable target);
public Thread(ThreadGroup group, Runnable target, String name)
public Thread(ThreadGroup group, Runnable target, String name,
long stackSize);
public Thread(ThreadGroup group, String name)
最后
这次是属于上篇文章的查漏补缺。内容不多,但是也需要掌握。
参考
How can the wait() and notify() methods be called on Objects that are not threads?
Why wait, notify and notifyAll is defined in Object Class and not on Thread class in Java
《高并发程序设计》
《并发编程的艺术》