多线程之启动,中止,及其他

启动线程

1.Runnable是Thread执行的逻辑
2.CallableFutureTask也是Thread要执行的逻辑,只是封装了获取结果的功能
因此: 启动线程的方式只有一种: new Thread().start();

终止线程

1.stop(不建议使用)

示例代码:

public class Demo_Stop {

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

        // 休眠1秒,确保i变量自增成功
        Thread.sleep(1000);
        thread.stop();

        // 确保线程已经终止
        while (thread.isAlive()) {}
        // 输出结果
        thread.print();
    }
}

class MyThread extends Thread {
    private int i = 0, j = 0;

    @Override
    public void run() {
        synchronized (this) {
            ++i;
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ++j;
        }
        System.out.println("锁释放。。。");
    }

    public void print() {
        System.out.println("i=" + i + " j=" + j);
    }
}

打印结果:
在这里插入图片描述
需要的输出结果应该是i=0 j=0;
stop方法没有保证同步代码看块中的数据一致性, 出现了线程安全问题

2.interrupt

示例代码:

public static void main(String[] args) throws InterruptedException {
        Thread workThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()) {
                    System.out.println("运行中");
                    try {
                        Thread.sleep(100L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        //将擦除掉的isInterrupted状态补上
                        Thread.currentThread().interrupt();
                    }
                }
            }
        });
        workThread.start();
        Thread.sleep(3000L);
        workThread.interrupt();
    }

注意点:

1.interrupt方法并不会中断线程,只是打上了中断标记

示例代码:

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

        //开启一个线程
        Thread testThread = new Thread(){
            @Override
            public void run() {
                while(true){
                    System.out.println("isInterrupted:" + Thread.currentThread().isInterrupted());
                    System.out.println("state:" + Thread.currentThread().getState());
                }
            }
        };

        testThread.start();
        Thread.sleep(2000);

        //调用interrupt方法,不会改变线程状态
        //并不会让线程退出,只是做了一个interrupt标记
        testThread.interrupt();
    }

输出结果:
在这里插入图片描述
可以看到,在sleep2秒后,isInterrupted的状态值由false变为了true

2.如果该线程在调用 wait(),wait(long)方法,join() 、 join(long, int) 、join(long, int)、sleep(long, int)或sleep(long, int)等方法后,处于WAITING、Timed Waiting状态时,在该线程被调用interrupt方法后,线程的WAITING、Timed Waiting状态将被清除,并抛出InterruptedException异常。

示例代码:

public static void main(String[] args) throws InterruptedException {
        Thread testThread = new Thread(){
            @Override
            public void run() {
                while (true){
                    try {
                        System.out.println("running...");
                        Thread.sleep(1000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        /*
                        当线程处于 Waiting、TimedWaiting状态,
                        执行interrupted方法后,会从Waiting、TimedWaiting中退出
                        并且isInterrupted=true的信号被擦除
                         */
                        System.out.println(Thread.currentThread().getState());
                        System.out.println("isInterrupted:" + Thread.currentThread().isInterrupted());
                    }
                }
            }
        };
        
        testThread.start();
        Thread.sleep(1000);
        testThread.interrupt();
    }

打印结果:
在这里插入图片描述

扫描二维码关注公众号,回复: 9303344 查看本文章

3.如果目标线程是被I/O 或者NIO中的Channel所阻塞,同样,I/O操作会被中断或者返回特
殊异常值。

4.park()\parkNanos方法执行后,线程也处于 WAITING、Timed Waiting,也会被唤醒,但是不会抛异常,且有很诡异的情况发生。

示例代码:

public static void main(String[] args) throws InterruptedException {
        Thread testThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    LockSupport.park();
                    System.out.println("ing...");
                }
            }
        });
        
        testThread.start();

        Thread.sleep(1000L);
        testThread.interrupt();

        System.out.println("============end=============================");

    }

打印结果
在这里插入图片描述

deamon线程

定义:

守护线程
是指在程序运行的时候在后台提供一种通用服务的线程,
进程结束时,会杀死所有守护线程。

注意点:

1.在Daemon线程中产生的新线程也是Daemon的
2.不能把正在运行的常规线程设置为守护线程,thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。
3.守护线程它会在任何时候甚至在一个操作的中间发生中断,因此应该永远不去访问固有资源,如文件、数据库等等

CountDownLatch倒计时器

作用:

countDownLatch可以使一个线程等待其他线程各自执行完毕后再执行。

示例代码:

public class Demo_CountDownLatch {

    static AtomicLong num = new AtomicLong(0);

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

        CountDownLatch ctl = new CountDownLatch(10);

        for (int i=0; i< 10; i++){
            new Thread(){
                @Override
                public void run() {
                    for (int j=0; j< 1000; j++){
                        num.getAndIncrement();
                    }
                    ctl.countDown();
                }
            }.start();
        }

        //设置开关,设置门栓
        ctl.await();
        System.out.println(num.get());
    }
}

Semaphore计数信号量

作用:

常用于限制可以访问某些资源(物理或逻辑的)线程数目。
是一种用来控制并发量的共享锁。

示例代码:

public class Demo_Semaphore {

    public static void main(String args[]){

        Semaphore sp = new Semaphore(10);

        //短时间发送1000个请求,并发会很高,数据库会受不了
        for (int i=0; i<1000; i++){
            new Thread(){
                @Override
                public void run() {
                    try {
                        sp.acquire();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    //模拟DB查询
                    queryDb("localhost:3306");
                    sp.release();
                }
            }.start();
        }

    }
    //发送一个HTTP请求
    public static void queryDb(String uri)  {
        System.out.println("query===>: " + uri);
        // 类似sleep的作用
        LockSupport.parkNanos(1000 * 1000 * 1000);
    }
}

CyclicBarrier循环栅栏

作用:

可以循环利用的屏障

示例代码:

public class Demo_CyclicBarrier {
    public static void main(String[] args) {

        CyclicBarrier barrier  = new CyclicBarrier(5,// 栅栏一次通过的请求数
                new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(">>> 这是一个栅栏。。。");
                    }
                });

        //传入一个Runnable,打印栅栏
        for (int i=0; i< 100; i++){
            new Thread(){
                @Override
                public void run() {
                    try {
                        barrier.await();    //
                        System.out.println("请求...");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
            LockSupport.parkNanos(1000 * 1000 * 1000L);
        }
    }
}
发布了53 篇原创文章 · 获赞 42 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_42815122/article/details/104412351