线程啊是个好东西,但是平时工作很少自己创建线程,所以一些基础的操作可能就不容易记起来,这篇文章常看看有益身心健康
1. 创建
 public class TestDeamon {    public static void main(String[] args) {        // lambda 表达式        Thread t1 = new Thread(()->System.out.println("这是一个线程01!"));        Thread t2 = new Thread(()->{            System.out.println("这是一个线程02!");        });        // 匿名内部类        Thread t3 = new Thread(){            @Override            public void run() {                System.out.println("这是一个线程03!");            }        };        // 继承Thread        Thread t4 =new MyThread04();
        // 实现Runnable 参数是Runnable        Thread t5 = new Thread(new MyRunnable());
        // 时效内        // 启动线程        t1.start();        t2.start();        t3.start();        t4.start();        t5.start();    }}
/** * 继承Thread * public class Thread implements Runnable * thread是实现了Runnable接口 */class MyThread04 extends  Thread{    @Override    public void run() {        System.out.println("这是一个线程04!");    }}
/** * 实现Runnable */class MyRunnable implements   Runnable{    @Override    public void run() {        System.out.println("这是一个线程05!");    }}
   复制代码
 2. 启动
 // 启动线程t1.start();t2.start();t3.start();t4.start();t5.start();输出:这是一个线程01!这是一个线程02!这是一个线程03!这是一个线程04!这是一个线程05!
   复制代码
 
线程启动之后就会执行 run 方法
3. 停止线程/中断
3.1. 线程执行完 自己结束
执行完 for 循环 自动结束
 // lambda 表达式        Thread t1 = new Thread(()->{            for (int i = 0; i < 10; i++) {                try{                    Thread.sleep(1000);                    System.out.println("===");                } catch (Exception e) {                    e.printStackTrace();                }            }        });        t1.start();
   复制代码
 
3.2. stop  被废弃了
stop 已经被废弃,stop 太粗暴,不温柔,所以没人喜欢..
  // lambda 表达式Thread t1 = new Thread(()->{    for (;;) {        try{            Thread.sleep(1000);            System.out.println("===");        } catch (Exception e) {            e.printStackTrace();        }    }});t1.start();// 10秒后 停止Thread.sleep(10000);// 停止t1.stop();
   复制代码
 
很容易产生数据不一致 因为某一个事务或者一块代码没执行完的时候 就有可能被干掉
举个例子:
 // lambda 表达式Thread t1 = new Thread(()->{    System.out.println("对象去洗澡了");    try{        System.out.println("钻被窝等着...");        Thread.sleep(10000);        System.out.println("洗白白 开小会");    } catch (Exception e) {        e.printStackTrace();    }});
t1.start();// 10秒后 停止Thread.sleep(5000);// 停止t1.stop();
结果:对象去洗澡了钻被窝等着...    可以看到哈,你等了半天,还没开始开小会就被打断了 。。  
   复制代码
 
3.3  suspend  resume 被废弃了
suspend  让线程暂停
resume 让暂停的线程继续执行
suspend 容易产生死锁等问题  如果忘记 resume 或者 resume 异常 那如果 suspend 的线程持有锁的话,就死锁了
 public class TestDeamon03 {    // 锁  表示对象    public static Object obj = new Object();    public static void main(String[] args) throws InterruptedException {
        // lambda 表达式        Thread t1 = new Thread(()->{                synchronized (obj){                   try {                       System.out.println("我出去打工了 留对象在家");                       Thread.sleep(10000);                       System.out.println("我回来了 娶我对象 ");                   } catch (Exception e) {                       e.printStackTrace();                   }                }        });
        t1.start();        // 2秒后 暂停        Thread.sleep(2000);        // 暂停        t1.suspend();        Thread.sleep(2000);    // 恢复         resumeObj(t1);    }
    // resume 模拟异常    static void resumeObj(Thread t){        int i = 1/0;        t.resume();    }}
   复制代码
 
你找了个对象,把人家放家里,说打工 1 年回来娶,然后你回家途中找了个别人,一起幸福生活了,你对象在家...
被你占用,你又不通知、不释放
3.4 volatile   结束
volatile(保证内存可见)修饰一个变量 时间可能控制不是很精确  因为 volatile 修改了之后刷新到内存 在另一个线程读取到 还是需要时间的 虽然很快 但是一般的情况 都没什么问题
 public class TestDeamon04 {    static volatile boolean flag = true;    public static void main(String[] args) throws InterruptedException {        // lambda 表达式        Thread t1 = new Thread(()->{            int count =0;            // flag == true 循环   flag==false 停止循环 也就结束线程了            while (flag) {                try {                    Thread.sleep(1);                    count++;                } catch (Exception e){                    e.printStackTrace();                }            }            System.out.println("count:"+count);        });
        t1.start();        // 1秒后 停止        Thread.sleep(1000);        flag = false;    }}
多次输出结果:    505、525、507、512 可以看到每次输出结果是不确定的 ,这种方式只能保证到达某个条件了就停止线程  但是不能控制线程准确点停止 比如你想让一个线程循环100次就停止 很难准确控制
   复制代码
 
3.5 interrupt  结束
也算标志位  但是比 volatile 高级一点 比如 sleep、wait 等操作会被中断
 // lambda 表达式final Thread t1 = new Thread(()->{    int count =0;    //    while (!Thread.interrupted()) {        try {            count++;        } catch (Exception e){            e.printStackTrace();        }    }    System.out.println("count:"+count);});
t1.start();// 1秒后 停止Thread.sleep(1000);t1.interrupt();
   复制代码
 
中断 sleep 测试:interrupt 会中断 sleep 在异常捕获里边 break 就行了 而标志位 flag 是无法做到的
 public class TestDeamon06 {    static volatile boolean flag = true;    public static void main(String[] args) throws InterruptedException {        // lambda 表达式        final Thread t1 = new Thread(()->{            //            while (!Thread.interrupted()) {                try {                    Thread.sleep(20000000);                } catch (Exception e){                    break;                }            }            System.out.println("interrupted 结束 ");        });
        // lambda 表达式        final Thread t2 = new Thread(()->{            while (flag) {                try {                    Thread.sleep(20000000);                } catch (Exception e){                    break;                }            }            System.out.println("volatile-结束");        });
        t1.start();        t2.start();        // 1秒后 停止        Thread.sleep(1000);        t1.interrupt();        flag = false;    }}
   复制代码
 
总结:
stop 、suspend resume 已废弃
volatile 标志位 无法中断 sleep wait 等操作
interrupt 相当于标志位但是可以中断 sleep wait 等操作 捕获 InterruptedException 异常 进行线程结束
可能还有其他方式 大多数是基于标志位的
欢迎关注公众号:
评论