美文网首页
2020-06-07

2020-06-07

作者: kaikaifly | 来源:发表于2020-06-07 21:01 被阅读0次

    [TOC]

    进程和线程的区别

    • 进程:每个进程都有独立的代码和数据空间,进程间的切换会有较大的开销,一个进程可以包含n个线程(进程是资源分配的最小单元)
    • 线程:同一类线程共享代码和数据空间,每个线程都有独立的运行栈和程序计数器,线程切换开销小(线程是cpu调度的最小单元)

    开启线程的三种方式

    • 继承Thread类
    • 实现Runnable接口
    • 实现Callable接口
    public class CallableThreadTest implements Callable<Integer> {
    
        public static void main(String[] args) {
            CallableThreadTest callableThreadTest = new CallableThreadTest();
            FutureTask<Integer> futureTask = new FutureTask<>(callableThreadTest);
    
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + " 的循环变量i的值" + i);
                if (i == 20) {
                    new Thread(futureTask, "有返回值的线程").start();
                }
            }
            try {
                System.out.println("子线程的返回值:" + futureTask.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
    
        }
    
        @Override
        public Integer call() throws Exception {
            {
                int i = 0;
                for (; i < 100; i++) {
                    System.out.println(Thread.currentThread().getName() + " " + i);
                }
                return i;
            }
        }
    }
    
    //Callable接口支持返回执行结果,此时需要调用FutureTask.get()方法实现,此方法会阻塞主线程直到获取‘将来’结果;当不调用此方法时,主线程不会阻塞
    

    实现Runnable接口比继承Thread类所具有的优势:

    1):适合多个相同的程序代码的线程去处理同一个资源

    2):可以避免java中的单继承的限制

    3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立

    4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类

    在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实际在就是在操作系统中启动了一个进程。

    线程状态转换

    thread.png
    1. 初始状态:新建线程对象
    2. 就绪状态:调用start()方法,等待获取cpu的使用权
    3. 运行状态:就绪状态获取cpu,执行程序代码
    4. 阻塞状态:线程因为某些原因放弃cpu的使用权,暂时停止运行,直到线程进入就绪状态,才有机会转到运行状态,
    5. 死亡状态:线程执行完毕,或者因异常退出run()方法,该线程结束生命周期

    Thread.sleep()

    使线程进入阻塞状态,等待sleep超时则进入就绪状态,而后等待cup资源恢复到运行状态,睡眠期间并不会释放所持有的对象锁,被其他对象调用它的interrupt()方法会产生InterruptExceptin异常,如果你的程序不捕获这个异常,线程就会异常终止,进入TERMINATED状态,如果你的程序捕获了这个异常,那么程序就会继续执行catch语句块(可能还有 finally语句块)以及以后的代码 。

    thread.join()

    thread.join()方法只会使主线程进入等待池并等待t线程执行完毕后才会被唤醒。并不影响同一时刻处在运行状态的其他线程

    class Thread1 extends Thread {
        private String name;
    
        public Thread1(String name) {
            super(name);
            this.name = name;
        }
    
        public void run() {
            System.out.println(Thread.currentThread().getName() + " 线程运行开始!");
            for (int i = 0; i < 5; i++) {
                System.out.println("子线程" + name + "运行 : " + i);
                try {
                    sleep((int) Math.random() * 10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + " 线程运行结束!");
        }
    
        public static void main(String[] args) {
            System.out.println(Thread.currentThread().getName() + "主线程运行开始!");
            Thread1 mTh1 = new Thread1("A");
            Thread1 mTh2 = new Thread1("B");
            mTh1.start();
            mTh2.start();
    
            try {
                mTh2.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "主线程运行结束!");
        }
    }
    //       main主线程运行开始!
    //        A 线程运行开始!
    //        B 线程运行开始!
    //        子线程A运行 : 0
    //        子线程B运行 : 0
    //        子线程A运行 : 1
    //        子线程B运行 : 1
    //        子线程A运行 : 2
    //        子线程B运行 : 2
    //        子线程B运行 : 3
    //        子线程A运行 : 3
    //        子线程B运行 : 4
    //        B 线程运行结束!
    //        子线程A运行 : 4
    //        main主线程运行结束!
    //        A 线程运行结束!
    

    相关文章

      网友评论

          本文标题:2020-06-07

          本文链接:https://www.haomeiwen.com/subject/rsshtktx.html