Java多线程-线程的启动和停止

线程的启动:

参考官方文档

Java多线程-线程的启动和停止_第1张图片

调用线程的start方法,通知jvm虚拟机去调用该线程的run方法,结果是两个线程并发的执行,一个是当前线程(调用start方法的线程),一个执行run方法的线程

如示例:

public class ThreadTest {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println(Thread.currentThread().getName());
        });
        thread.start();
        System.out.println(Thread.currentThread().getName());
    }
}

打印出两个线程名称为:

main 执行start方法d main线程
Thread-0  新建的执行run方法的线程0

注意的点:

1.多个线程start方法的顺序并不能决定线程真正执行的顺序。

需要等待CPU的资源,是异步随机执行的,如下示例:

public class ThreadTest {
    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + ": run");
            }
        };
        Thread thread1 = new Thread(r);
        Thread thread2 = new Thread(r);
        Thread thread3 = new Thread(r);
        Thread thread4 = new Thread(r);
        Thread thread5 = new Thread(r);
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
        thread5.start();
    }
}

打印结果是随机的:

Thread-0: run
Thread-2: run
Thread-1: run
Thread-3: run
Thread-4: run

2.start方法不能重复调用,哪怕线程已经执行完毕也不能再次执行,否则将抛出线程状态异常,后面说线程的状态可以了解。

3.和run方法的区别:为什么不用run方法启动线程

如文档解释,start方法是当前线程执行start方法,告诉jvm虚拟机用新建的线程是执行run方法。而run方法就是当前线程之间执行了run方法,并没有使用新建的线程。

停止线程:

使用interrupt()方法中断线程,需要注意的是,该方法是一个线程去通知另一个线程去中断,被中断的线程自身决定是否停止,非强行停止;

思考如下

被停止线程更清楚该如何停止,比如某个线程a正在执行run方法,如果其它线程b调用了a的interrupt()方法通知其停止,a应该自身决定如何响应,是继续执行,还是纪录一些日志,处理完一个阶段的业务再停止,如果a被b强制停止,则a执行的业务将产生脏数据,安全性较差。所以停止线程的最佳方法就是通知该线程去停止,该线程可以自行判断自身是否已被中断(

isInterrupted()方法判断),然后合理响应;stop()方法,强制停止,已过时;

示例:

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("我一直在执行");
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("好的,我停止了");
                        break;
                    }
                }
            }
        };
        Thread thread = new Thread(r);
        thread.start();
        Thread.sleep(10);
        thread.interrupt();
    }
}

打印结果:

...
我一直在执行
我一直在执行
我一直在执行
我一直在执行
我一直在执行
好的,我停止了

如代码示例,被通知中断的线程配合做了处理(if判断)自主决定中断还是继续执行;

进一步考虑,如果线程没有在执行,而是在阻塞状态,如下run示例:

public void run() {
                while (true) {
                    System.out.println("我一直在执行");
                    Thread.sleep(10000);
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("好的,我停止了");
                        break;
                    }
                }
            }

线程阻塞在sleep方法时,这时候外部线程通知中断,但这里已经阻塞无法进到if判断,该如何响应,sleep方法已经考虑到了,这个方法强制要求我们处理InterruptedException异常,即中断异常,来响应外部的中断通知。

如示例:


public void run() {
                while (true) {
                    System.out.println("我一直在执行");
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        System.out.println("好的我知道了");
                    }
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("好的,我停止了");
                        break;
                    }
                }
            }

另外修改后的方法实际执行的话,while循环并没有停止,线程并没有结束,这是为什么呢?这是因为抛出异常的同时会将该线程的isInterrupted重置为false;可以查看InterruptedException的注释:

Java多线程-线程的启动和停止_第2张图片

抛出InterruptedException的时候,会清除是否中断的标记位!

其它

如果run方法执行完毕或抛出异常,该线程也会停止;

--- END ---

马上关注    /    码上杂谈

你可能感兴趣的:(java,多线程)