Java多线程技能

1 分析线程的工具

1.1 visualVM

JDK自带,监控工具在bin/jvisualvm.exe,能监控线程,内存情况,查看方法的CPU时间和内存中的对象,已被GC的对象,反向查看分配的堆栈(如100个String对象分别由哪几个对象分配出来的)。

自动显示当前本机所运行的Java程序,还可添加远程的Java VM。

2 停止线程

2.1 stop() 已过期

public class StopThread1 {

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            int count = 0;
            System.out.println("线程开始....");
            for (int i = 0; i < 20; i++) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) { // stop()方法不会抛出这个错
                    throw new RuntimeException(e);
                }
                count++;
            }
            System.out.println("线程结束....count:" + count);
        });
        thread.start();
        TimeUnit.SECONDS.sleep(5);
        thread.stop(); //线程中会抛出ThreadDeath错误
    }

}

图 stop停止线程方法运行结果

stop()方法:强制线程停止执行。不能确定线程在哪里被停止了。

2.2 interrupt()

public class StopThread2 {

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            int count = 0;
            try {
                System.out.println("线程开始....");
                for (int i = 0; i < 20; i++) {
                    TimeUnit.SECONDS.sleep(1);
                    count++;
                }
            } catch (InterruptedException e) {
                System.out.println("线程结束....count:" + count);
            }
        });
        thread.start();
        TimeUnit.SECONDS.sleep(5);
        thread.interrupt();
    }

}

图 interrupt停止线程运行结果

interrupt()中断线程,在线程中通过异常法来停止线程,能确定线程在哪里被停止及可以及时处理任务。

2.2.1 interrupted() 与 isInterrupted()

1) public static boolean interrupted(): 测试currentThread() 是否已经中断。当前线程是指执行this.interrupted()方法的线程。

2)public boolean this.isInterrupted():测试this关键字所在线程类的对象是否已经中断。

图 interrupted方法源码

执行interrupted()方法后,中断标志会被清除(线程状态从中断恢复成正常)。

3 暂停线程

3.1 suspend() 已过期

public class SuspendThread {

    private static class SyncService {
        public void show() {
            System.out.println("thread:" + Thread.currentThread().getName());
            Thread.currentThread().suspend();
        }
    }

    public static void main(String[] args) throws InterruptedException {

        SyncService syncService = new SyncService();

        Thread thread1 = new Thread(() -> {
            syncService.show();
        });
        thread1.setName("thread1");

        thread1.start();
        thread1.resume(); //该操作可能会早于show()方法里面的suspend操作
    }

}

图 线程一直被挂起

3.2 LockSupport

public class LockSupportThread {

    private static class SyncService {
        public void show() throws InterruptedException {
            System.out.println("thread:" + Thread.currentThread().getName());
            TimeUnit.SECONDS.sleep(1);
            LockSupport.park();
        }
    }

    public static void main(String[] args) throws InterruptedException {

        SyncService syncService = new SyncService();

        Thread thread1 = new Thread(() -> {
            try {
                syncService.show();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        thread1.setName("thread1");

        thread1.start();
        LockSupport.unpark(thread1); //该操作早于show()方法里面的park操作
    }

}

图 线程正常结束 

即使unpack()操作发生在pack()之前,它也可以使下一次的pack()操作立即返回。

另外,suspend()执行的线程状态为运行状态,pack()执行的线程状态为等待。

图 绿色代表运行,黄色代表等待 

4 线程优先级

Java中线程的优先级分为10个等级,即1~10。

4.1 优先级的三个特性

1) 可继承性:比如A线程启动B线程,则B线程的优先级与A是一样的。

2)规律性:CPU会尽量将执行资源让给优先级较高的线程。

3)随机性:优先级较高的线程不一定每次都先执行完。

5 守护线程

Java中有两种线程,一种是用户线程,也称非守护线程;另一种是守护线程。

守护线程是一种特殊的线程,当进程中不存在非守护线程时,则守护线程自动销毁。典型的守护线程就是垃圾回收线程。

主线程main也属于用户线程。凡是调用setDaemon(true)的线程才是守护线程。

public class DaemonThread {

    private static class MyThread extends Thread {
        @Override
        public void run() {
            try {
                System.out.println("守护线程开始");
                TimeUnit.SECONDS.sleep(50);
                System.out.println("守护线程结束");
            } catch (InterruptedException e) {
                System.out.println("守护线程被终止");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        myThread.setDaemon(true);
        myThread.start();
        TimeUnit.SECONDS.sleep(2);
        System.out.println("main线程执行完毕");
    }

}

 图 守护线程执行结果

6 并发与并行

并发是逻辑上的同时存在,而并行是物理上的同时存在。

并发是指多线程逻辑上,在同一时间执行。但是实际在CPU上每个线程分配了时间片,线程按顺序执行。

并行是多核CPU,两个线程分别在不同CPU上同一时间执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值