# Java拾遗-并发-Thread

一个个小例子深入了解知识点

# 1. Thread

/**
 * 线程的创建方式一 - 继承Thread
 * 线程的创建方式二 - 实现Runnable
 * 线程的创建方式三 - JDK8直接创建
 *
 * 请你告诉我启动线程的三种方式 1:Thread 2: Runnable 3:Executors.newCachedThrad
 *
 * @author wliduo[i@dolyw.com]
 * @date 2020/4/14 10:20
 */
public class T01_Thread {

    private static class CreateThread1 extends Thread {

        @Override
        public void run() {
            // CreateThread1线程循环打印
            for (int i = 0; i < 50; i++) {
                try {
                    // 休眠1S,不然无法时时切换线程
                    TimeUnit.MICROSECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("CreateThread1");
            }
        }

    }

    private static class CreateThread2 implements Runnable {

        @Override
        public void run() {
            // CreateThread2线程循环打印
            for (int i = 50; i < 100; i++) {
                try {
                    // 休眠1S,不然无法时时切换线程
                    TimeUnit.MICROSECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("CreateThread2");
            }
        }

    }

    public static void main(String[] args) {
        // 线程的创建方式一 - 继承Thread
        CreateThread1 createThread1 = new CreateThread1();
        // 启动线程
        createThread1.start();
        // 线程的创建方式二 - 实现Runnable
        Thread createThread2 = new Thread(new CreateThread2());
        // 启动线程
        createThread2.start();
        // 线程的创建方式三 - JDK8直接创建
        new Thread(() -> {
            for (int i = 0; i < 50; i++) {
                try {
                    // 休眠1S,不然无法时时切换线程
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("CreateThread3");
            }
        }).start();
        // 主线程循环打印
        for (int i = 50; i < 100; i++) {
            try {
                // 休眠1S,不然无法时时切换线程
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Main");
        }
    }

    /**
     * JAVA中让当前线程睡眠一段时间的方式
     * 方法一:通过线程的sleep方法
     * Thread.sleep(1000);
     * Thread.currentThread().sleep(1000);
     * 上面两种没区别,参数1000是以毫秒为单位,即这语句可以让程序等待1秒
     * 方法二:TimeUnit类里的sleep方法
     * java.util.concurrent.TimeUnit;这个类里封装着
     * TimeUnit.DAYS.sleep(1); //天
     * TimeUnit.HOURS.sleep(1); //小时
     * TimeUnit.MINUTES.sleep(1); //分
     * TimeUnit.SECONDS.sleep(1); //秒
     * TimeUnit.MILLISECONDS.sleep(1000); //毫秒
     * TimeUnit.MICROSECONDS.sleep(1000); //微妙
     * TimeUnit.NANOSECONDS.sleep(1000); //纳秒
     * TimeUnit类提供的方法,底层调用的也是Thread类的sleep方法,只是在上层根据时间单位进行封装
     */
}

# 2. yield

/**
 * 了解一下就行 - 线程的休眠方式 - Thread.yield()
 * Thread.yield()与Thread.sleep(1000)或者TimeUnit.MILLISECONDS.sleep(1000)区别
 * 主要是前两者都是存在指定休眠时间,时间到了才能继续执行,而Thread.yield()只是让步
 * 就是当前线程让出当前时间片给其他线程执行,继续回到等待队列,也可能可能再次被选中执行
 *
 * yield()方法会通知线程调度器放弃对处理器的占用,但调度器可以忽视这个通知。
 * yield()方法主要是为了保障线程间调度的连续性,防止某个线程一直长时间占用cpu资源。
 * 但是他的使用应该基于详细的分析和测试。
 * 这个方法一般不推荐使用,它主要用于debug和测试程序,用来减少bug以及对于并发程序结构的设计
 *
 * @author wliduo[i@dolyw.com]
 * @date 2020/4/14 10:20
 */
public class T02_yield {

    private static class CreateThread implements Runnable {

        @Override
        public void run() {
            // CreateThread线程循环打印
            for (int i = 0; i < 50; i++) {
                System.out.println("CreateThread3");
            }
        }

    }

    public static void main(String[] args) {
        Thread thread = new Thread(new CreateThread());
        // 启动线程
        thread.start();
        // 写法
        Thread.yield();
        // 主线程循环打印
        for (int i = 0; i < 50; i++) {
            System.out.println("Main3");
        }
    }

    /**
     * JAVA中可以通过让当前线程睡眠一段时间的方式
     * 方法一:通过线程的sleep方法
     * Thread.sleep(1000);
     * Thread.currentThread().sleep(1000);
     * 上面两种没区别,参数1000是以毫秒为单位,即这语句可以让程序等待1秒
     * 方法二:TimeUnit类里的sleep方法
     * java.util.concurrent.TimeUnit;这个类里封装着
     * TimeUnit.DAYS.sleep(1); //天
     * TimeUnit.HOURS.sleep(1); //小时
     * TimeUnit.MINUTES.sleep(1); //分
     * TimeUnit.SECONDS.sleep(1); //秒
     * TimeUnit.MILLISECONDS.sleep(1000); //毫秒
     * TimeUnit.MICROSECONDS.sleep(1000); //微妙
     * TimeUnit.NANOSECONDS.sleep(1000); //纳秒
     * TimeUnit类提供的方法,底层调用的也是Thread类的sleep方法,只是在上层根据时间单位进行封装
     */
}

# 3. join

/**
 * 线程的方法 - join()
 * 调用某线程的某方法,将当前线程和该线程合并,等待该线程结束,再恢复当前线程的允许
 *
 * createThread1.join();
 * createThread2.join();
 * 主线程调用join(),线程1,2交替执行
 *
 * 如果完全按顺序执行,主线程调用线程2的join(),线程2内run方法第一行调用线程1的join()
 *
 * 当我们在join()方法中传入参数时,比如1000,那么主线程只会阻塞1000ms,然后就恢复了并行的执行状态
 * 简单说就是只会等待子线程执行1000ms
 *
 * @author wliduo[i@dolyw.com]
 * @date 2020/4/14 10:20
 */
public class T03_join {

    public static void main(String[] args) {
        // 创建线程一
        Thread createThread1 = new Thread(() -> {
            // CreateThread1线程循环打印
            for (int i = 0; i < 10; i++) {
                try {
                    // 休眠1S,不然无法时时切换线程
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("CreateThread1");
            }
        });
        // 创建线程二
        Thread createThread2 = new Thread(() -> {
            try {
                // 线程二里调用线程一的join()
                createThread1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // CreateThread2线程循环打印
            for (int i = 20; i < 30; i++) {
                try {
                    // 休眠1S,不然无法时时切换线程
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("CreateThread2");
            }
        });
        // 启动线程
        createThread1.start();
        createThread2.start();
        /*try {
            // 主线程调用join(),线程1,2交替执行
            createThread1.join();
            createThread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        try {
            // 如果完全按顺序执行,主线程调用线程2的join(),线程2内run方法第一行调用线程1的join()
            // createThread2.join();
            // 当我们在join()方法中传入参数时,比如1000,那么主线程只会阻塞1000ms,然后就恢复了并行的执行状态
            // createThread2.join(1000);
            // 参数区别第一个是毫秒,第二个是纳秒,等待时间就是毫秒+纳秒,时间更精确
            createThread2.join(1000, 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 主线程循环打印
        for (int i = 1; i < 10; i++) {
            try {
                // 休眠1S,不然无法时时切换线程
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Main");
        }
    }
}

# 4. State

/**
 * 线程的状态 - getState() - State枚举
 *
 * NEW,新建状态,尚未启动的线程的线程状态
 *
 * RUNNABLE,可运行线程的线程状态,可运行程序中的线程,
 * 状态正在Java虚拟机中执行,但它可能正在等待来自操作系统的其他资源,例如处理器
 *
 * BLOCKED,等待监视器锁定时被阻止的线程的线程状态,
 * 处于阻塞状态的线程正在等待监视器锁定输入同步块/方法或调用后重新输入同步的块/方法 Object.wait()
 *
 * WAITING,等待线程的线程状态,由于调用以下方法 Object.wait()没有超时 Thread.join()没有超时 LockSupport.park()
 * 处于等待状态的线程正在等待另一个线程执行特定的动作
 *
 * TIMED_WAITING,具有指定等待时间的等待线程的线程状态,由于调用具有指定正等待时间的以下方法
 * Thread.sleep() Object.wait() Thread.join() LockSupport.parknos() LockSupport.parkUntil()
 *
 * TERMINATED,终止线程的线程状态,线程已完成执行
 *
 * @author wliduo[i@dolyw.com]
 * @date 2020/4/14 10:20
 */
public class T04_State {

    public static void main(String[] args) {
        // 创建线程
        Thread thread = new Thread(() -> {
            System.out.println("-----" + Thread.currentThread().getState());
            // 线程循环打印
            for (int i = 0; i < 5; i++) {
                try {
                    // 休眠1ms,不然无法时时切换线程
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("-----" + Thread.currentThread().getState());
                System.out.println("Thread");
            }
            System.out.println("-----" + Thread.currentThread().getState());
        }, "diy-thread");
        System.out.println("-----" + thread.getState().name());
        // 启动线程
        thread.start();
        System.out.println("-----" + thread.getState().name());
        // 主线程循环打印
        for (int i = 10; i < 15; i++) {
            try {
                // 休眠1ms,不然无法时时切换线程
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Main");
        }
        try {
            // 先执行完thread线程
            thread.join();
            System.out.println("-----" + thread.getState());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("-----" + thread.getState());
    }
}
上次更新时间: 2023-12-15 03:14:55