1 线程

1.1 Thread

下面是两个demo,第一个是线程执行顺序,第二个是多个线程的顺序。

其中线程的start可以看成是就绪状态,cpu并不一定会马上去执行run方法的内容,因此如果是多线程,顺序是不确定的。

public class Thread01 extends Thread{
    public static void main(String[] args) {
        System.out.println("JVM创建main线程执行main方法");

        Thread01 thread01 = new Thread01();
        //调用start()方法来启动线程,实质就是请求JVM运行相应的线程,这个线程具体什么时候运行由OS的线程调度器(Scheduler)决定
        //start()方法调用结束并不意味着子线程开始运行
        //新开启的进行会执行run方法
        //如果开启了多个线程,start()调用的顺序并不一定就是线程的启动顺序!
        //多线程运行结果和代码调用顺序无关
        thread01.start();

        System.out.println("main线程其他的代码...");
    }

    //run()方法的代码就是子线程要执行的任务
    //run()方法执行完线程就执行完了
    @Override
    public void run() {
        System.out.println("这是子线程打印的东西");
    }
}

线程的执行顺序,main方法也是一个线程

java多线程执行完毕再 java中多线程执行顺序_jvm

public class Thread02 extends Thread {

    public static void main(String[] args) throws InterruptedException {
        Thread02 thread02 = new Thread02();
        thread02.start();

        for (int i = 0; i < 10; ++i) {
            System.out.println("main thread: " + i);
            long time = (long) (Math.random() * 1000);
            Thread.sleep(time);
        }
    }

    @SneakyThrows
    @Override
    public void run() {
        for (int i = 0; i < 10; ++i) {
            System.out.println("sub thread: " + i);
            long time = (long) (Math.random() * 1000);
            Thread.sleep(time);
        }
    }
}

因为只执行10循环,线程运行很快,循环100次可能都不会出现顺序不同,所以让主线程sleep一会,就可以看到主和子线程交替执行。

java多线程执行完毕再 java中多线程执行顺序_jvm_02

1.2 Runnable和Callable区别

1)Runnable提供run方法,无法通过throws抛出异常,所有CheckedException必须在run方法内部处理。Callable提供call方法,直接抛出Exception异常。

2)Runnable的run方法无返回值,Callable的call方法提供返回值用来表示任务运行的结果。

3)Runnable可以作为Thread构造器的参数,通过开启新的线程来执行,也可以通过线程池来执行。而Callable只能通过线程池执行。

同样顺序不同,可自己运行

public class MyRunnable implements Runnable {

    // 2)重写Runnable接口中的抽象方法run()
    // run()方法就是子线程要执行的代码
    @Override
    public void run() {
        for(int i = 0; i < 10; i++){
            System.out.println("sub thread -> " + i);
        }
    }

    public static void main(String[] args) {
        // 3)创建Runnable接口的实现类对象
        MyRunnable runnable = new MyRunnable();
        // 4)创建线程对象
        Thread t = new Thread(runnable);
        // 5) 启动线程
        t.start();


        for(int i = 0; i < 10; i++)
            System.out.println("main thread -> " + i);
    }
}

2 多线程

主要介绍五种

  • cachedThreadPool():线程池的最大核心线程为无限大,当执行第二个任务时第一个任务已经完成,则会复用执行第一个任务的线程;如果第一个线程任务还没有完成则会新建一个线程。
  • fixedThreadPool(2):创建指定长度的线程池,任务超出当前线程池执行线程数量则会一直等待,直到运行。
  • scheduledThreadPool:支持创建定时线程池,以下案例中延迟2秒后开始执行线程池中的所有任务。
  • singleThreadExecutor:创建一个单线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
  • threadPoolExecutor:详解
public class ThreadPool {

    public static void main(String[] args) {
        // 总结: 线程池的最大核心线程为无限大,当执行第二个任务时第一个任务已经完成,则会复用执行第一个任务的线程;如果第一个线程任务还没有完成则会新建一个线程。
        //cachedThreadPool();
        // 总结:创建指定长度的线程池,任务超出当前线程池执行线程数量则会一直等待,直到运行。
        //fixedThreadPool();
        // 总结:以下案例中延迟2秒后开始执行线程池中的所有任务。
        //scheduledThreadPool();
        // 创建一个单线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
        //singleThreadExecutor();
        threadPoolExecutor();
    }

    public static void cachedThreadPool() {
        // 创建可缓存线程池
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();

        for (int i = 0; i < 5; i++) {
            //创建任务
            Runnable runnable = () -> {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
            };
            newCachedThreadPool.execute(runnable);
        }
    }

    public static void fixedThreadPool() {
        // 创建定长线程池
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);

        for (int i = 0; i < 5; i++) {
            //创建任务
            Runnable runnable = () -> {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
            };
            // 将任务交给线程池管理
            newFixedThreadPool.execute(runnable);
        }
    }

    public static void scheduledThreadPool() {
        // 创建支持定时线程池
        ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(2);

        for (int i = 0; i < 5; i++) {
            //创建任务
            Runnable runnable = () -> System.out.println(Thread.currentThread().getName());
            // 将任务交给线程池管理,延迟2秒后才开始执行线程池中的所有任务
            newScheduledThreadPool.schedule(runnable, 2, TimeUnit.SECONDS);
        }
    }

    public static void singleThreadExecutor() {
        // 创建单线程-线程池,任务依次执行
        ExecutorService newScheduledThreadPool = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 5; i++) {
            //创建任务
            Runnable runnable = () -> System.out.println(Thread.currentThread().getName());
            // 将任务交给线程池管理
            newScheduledThreadPool.execute(runnable);
        }
    }

    public static void threadPoolExecutor() {

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1024));
        for (int i = 0; i < 5; i++) {
            //创建任务
            Runnable runnable = () -> System.out.println(Thread.currentThread().getName());
            // 将任务交给线程池管理
            threadPoolExecutor.execute(runnable);
        }
    }

}