多线程学习笔记1-基础知识

多线程基础

1. Thread名称

Thread默认有一个名称, 以Thread-开头,从0开始计数。

2. Thread中若没有传递runnable实例。同样可以运行。

3. Thread Group

若创建线程的时候,没有指定ThreadGroup则使用的是父线程的ThreadGroup。两者线程会在同一个ThreadGroup中。

4. StackSize

  1. 此为Thread的构造函数参数,表示此线程可以使用的栈大小,而不是使用JVM默认分配的大小。若是没有指定此参数,则默认为0,代表忽略此参数,该参数会被JNI调用。
  2. 此参数在有的平台生效,有的平台不会生效。

5. Daemon

当父线程结束,此线程也会结束,不会挂在后台一直执行。 Daemon必须放在start之后执行,否则报错异常。

6. Join

只针对 join之后的线程,必须得等join之前的线程执行完成,才能往下面执行。join可以设置衣蛾timeOut,表示join多久,超过此时间段,则接着往下面执行代码。 join必须放在start之后,才能起效;但是,放start之前也不会报错。

7. Interrupt

当调用Interrupt方法的时候,若在线程中使用了sleep, wait,join这些方法,会导致线程抛出中断异常,关闭线程。 interrupt是中断被join的那个线程。

8. 关闭一个Thread(Grace For Close Thread)

  1. 原来的jdk中使用的是stop方法来关闭一个线程,后来因为此方法关闭线程会产生一系列问题。因此,此方法不再推荐使用。
  2. 解决方法:
    1. 使用Volatile修饰的一个boolean值,使用while监控此线程,什么时候推出程序。 使用volatile的原因。因为,普通的属性是在每个线程中单独存在各自的副本,修改不糊影响到其它线程中。而Volatile则强制要求线程更新了数据,其它线程需要重新load数据。保证数据的正确性。
public class ThreadInterruptDemo {

    private static class Worker extends Thread {
        private volatile boolean is_Down = false;

        @Override
        public void run() {
            while (is_Down) {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        public void shutDown() {
            this.is_Down = true;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Worker worker = new Worker();

        worker.start();

        Thread.sleep(10_000);

        worker.shutDown();
    }
}
  1. 使用中断(Interrupt)机制来退出线程:调用线程的Interrupt方法,然后,在方法中再次调用线程的sleep, join, wait方法,可以导致线程抛出中断异常,从而导致线程的退出。
public class ThreadInterruptDemo2 {

    private static class Worker extends Thread {

        @Override
        public void run() {
            while (true) {
                if (Thread.interrupted()) { // 若中断, 则退出线程.
                    return;
                }

                System.out.println("ing.........");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Worker worker = new Worker();

        worker.start();

        Thread.sleep(3_000);

        worker.interrupt();
    }
}

9. 强制关闭一个线程(Force close Thread)

不推荐使用stop方法。而可以使用守护线程的方法,关闭主要线程,从而导致执行任务的守护线程的退出。

public class ThreadService {

    private Thread executeThread;

    private boolean finished = false;

    public void execute(Runnable task) {        executeThread = new Thread(() -> {
            Thread runner = new Thread(task); //真正执行任务的线程.
            runner.setDaemon(true); // 设置为守护线程, 则只需要主线程退出, 守护线程也就退出了.
            runner.start();

            try {                runner.join(); // 拦截代码往下面执行.等待任务执行完成.
                finished = true;
            } catch (InterruptedException e) {                System.out.println("触发中断异常");
            }        });

        executeThread.start();
    }
    /**
     * 外部其它线程, 调用此方法关闭executeThread,
     * 从而保证了可以强制关闭runner(执行任务线程)的关闭.
     * @param  maxSpendTime: 此任务最大可以消耗的时间, 超时则关闭此任务.
     */
    public void shutDown(long maxSpendTime) {        long currentTimeMillis = System.currentTimeMillis();
        while (!finished) {            long endTime = System.currentTimeMillis();
            if ((endTime - currentTimeMillis) >= maxSpendTime) {                System.out.println("此任务超时....");
                executeThread.interrupt(); //使用了join, 产生中断异常.
                break;
            }
            try {
                executeThread.sleep(1);
            } catch (InterruptedException e) {                System.out.println("执行线程被中断");
                break;
            }        }

        finished = false;
    }}



public class CloseThreadMain {

    public static void main(String[] args) {
        ThreadService service = new ThreadService();
        long currentTimeMillis = System.currentTimeMillis();
        service.execute(() -> {            // 执行一个长时间任务.
            while (true) { // 触发中断异常

            }
            /*try { // 正常任务执行结束.
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
        });

        service.shutDown(10000); //制定超过多少时间, 关闭此线程.
        long endTime = System.currentTimeMillis();
        System.out.println(endTime - currentTimeMillis);  // 得到线程花费时间.
}}

猜你喜欢

转载自blog.csdn.net/weixin_38608626/article/details/93380862