多线程2——>线程的常用方法及线程间的通信

一.线程的常用方法

1.构造方法和属性的获取方法

构造方法:
在这里插入图片描述
属性的获取方法:
在这里插入图片描述

2.常用方法

<1>.run()和start()

start();方法:启动线程
run();方法:覆写 run 方法是提供给线程要做的事情的指令清单

注意:
run和start的区别:

public class Thread_Run_VS_Start {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){

                }
            }
        }).run();
        /**
         * main线程直接调用Thread对象的run方法会直接在main线程
         * 运行Thread对象的run()方法---->传入的runnable对象.run()
         * 结果,main线程直接运行while(true)
         *
         * start()是启动一个线程
         * 对比通过start()调用的结果区别
         */

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){

                }
            }
        }).start();
    }
}

<2>.中断线程interrupt()方法

在这里插入图片描述
通过interrupt()方法,通知线程中的中断标志位,由false变为true,但是线程什么时候中断,需要线程自己的代码实现
通过线程中的中断标志位实现,比起自己手动设置中断标志位,可以避免线程处于阻塞状态下,无法中断的情况

通过代码演示:

public class Interrupt {
    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(new Runnable() {
            @Override
            public void run() {

                //...执行任务,执行时间可能比较长
                //运行到这里,在t的构造方法中不能引用t使用Thread.currentThread()方法,获取当前代码行所在线程的引用
                for (int i = 0; i <10000&&!Thread.currentThread().isInterrupted() ; i++) {
                    System.out.println(i);
                    //模拟中断线程
                    try {
                        Thread.sleep(1000);
                        //通过标志位自行实现,无法解决线程阻塞导致无法中断
                        //Thread,sleep(100000)
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.start();//线程启动,中断标志位=false
        System.out.println("t start");
        //模拟,t执行了5秒,进程没有结束,要中断,停止t线程
        Thread.sleep(5000);

        //未设置时,isInterrupt为false

        //如果t线程处于阻塞状态(休眠等),会抛出InterruptedException异常
        //并且会重置isInterrupt中断标志位位false
        t.interrupt();//告诉t线程,要中断(设置t线程的中断标志位为true),由t的代码自行决定是否要中断
        //isInterrupt设置为true
        //t.isInterrupted();  Interrupted是线程中的标志位
        System.out.println("t stop");


        //注:Thread.interrupted(); 返回当前线程的中断标志位,然后重置中断标志位
         
    }
}

<3>.等待一个线程join()方法

注意: join方法是实例方法
等待一个线程执行完毕,才执行下一个线程
在这里插入图片描述

无参:t.join:当前线程无条件等待,直到t线程运行完毕
在这里插入图片描述

有参:t.join(1000)等待1秒,或者t线程结束,哪个条件满足,当前线程继续往下执行

//join方法:实例方法:
// 1.无参:t.join:当前线程无条件等待,直到t线程运行完毕
//  2.有参:t.join(1000)等待1秒,或者t线程结束,哪个条件满足,当前线程继续往下执行
public class Join {
    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("1");
            }
        });
        t.start();

        t.join();//当前线程main线程无条件等待,直到t线程执行完毕,当前线程再往后执行
       // t.join(1000);当前线程等到1秒,或者等t线程执行完毕
        System.out.println("ok");

    }
}

<4>.获取当前线程的引用currentThread();方法

在这里插入图片描述

public class ThreadDemo { 
public static void main(String[] args) { 
Thread thread = Thread.currentThread(); 
System.out.println(thread.getName()); 
} 
}

<5>.休眠当前线程sleep();方法

在这里插入图片描述
让线程等待一定时间后,继续运行

<6>.线程让步yield();方法

让yield();所在代码行的线程让步,当其他线程先执行

public class Yield {
    public static void main(String[] args) {
        for(int i=0;i<20;i++){
            final int n=i;
            Thread t=new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(n);
                }
            });
            t.start();
        }
        //判断:如果活跃的线程数量大于1,main线程让步
        while (Thread.activeCount()>1){//记录活跃线程的数量
            Thread.yield();
        }//注意:要用debug方式,因为run方式,idea后台还会启动一个线程
        //实现ok在1到二十之后打印
        System.out.println("ok");
    }
}

二.线程间的通信

1.线程的状态和转移

在这里插入图片描述
在这里插入图片描述

2.线程间的通信方法

wait(0方法:线程等待
notify();方法:随机唤醒一个线程
notifyAll():方法:唤醒所有等待的线程
注意:这三个方法都需要被Synchronized包裹
在这里插入图片描述
线程间通信的案例:
有三个线程,每个线程只能打印A,B或C
要求:同时执行三个线程,按ABC顺序打印,依次打印十次
ABC换行 ABC换行。。。。
考察知识点:代码设计,多线程通信

public class SequencePrintHomeWork {
    //有三个线程,每个线程只能打印A,B或C
    //要求:同时执行三个线程,按ABC顺序打印,依次打印十次
    //ABC换行 ABC换行。。。。
    //考察知识点:代码设计,多线程通信

    public static void main(String[] args) {
        Thread a = new Thread(new Task("A"));
        Thread b = new Thread(new Task("B"));
        Thread c = new Thread(new Task("C"));
        c.start();
        b.start();
        a.start();
    }

    private static class Task implements Runnable{

        private String content;
        //顺序打印的内容:可以循环打印
        private static String[] ARR = {"A", "B", "C"};
        private static int INDEX;//从数组哪个索引打印

        public Task(String content) {
            this.content = content;
        }

        @Override
        public void run() {
            try {
                for(int i=0; i<10; i++){
                    synchronized (ARR){//三个线程使用同一把锁
                        //从数组索引位置打印,如果当前线程要打印的内容不一致,释放对象锁等待
                        while(!content.equals(ARR[INDEX])){
                            ARR.wait();
                        }
                        //如果数组要打印的内容和当前线程要打印的一致,
                        // 就打印,并把数组索引切换到一个位置,通知其他线程
                        System.out.print(content);
                        if(INDEX==ARR.length-1){
                            System.out.println();
                        }
                        INDEX = (INDEX+1)%ARR.length;
                        ARR.notifyAll();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

补充: wait()和sleep()的区别:

  1. wait 之前需要请求锁,而wait执行时会先释放锁,等被唤醒时再重新请求锁。这个锁是 wait 对象上的 monitor
    lock
  2. sleep 是无视锁的存在的,即之前请求的锁不会释放,没有锁也不会请求。
  3. wait 是 Object 的方法
  4. sleep 是 Thread 的静态方法
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Serendipity sn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值