java基础学习14(线程通讯、守护线程、线程的停止、线程的加入)

线程通讯

  • wait(): 等待 如果线程执行了wait方法,那么该线程会进入等待的状态,等待状态下的线程必须要被其他线程调用notify方法才能唤醒。
  • notify(): 唤醒 唤醒线程池等待线程其中的一个。
  • notifyAll() : 唤醒线程池所有等待 线程。

wait与notify方法要注意的事项:
1. wait方法与notify方法是属于Object对象 的。
2. wait方法与notify方法必须要在同步代码块或者是同步函数中才能使用,且必需要由锁对象调用。

class Product{
    public String name;

    public float price;

    public boolean flag = false;//是否消费

    public Product() {
    }
}

class Producer implements Runnable{
    Product p;

    public Producer(Product p) {
        this.p = p;
    }


    @Override
    public void run() {
        int i = 0;
        while(true) {
            synchronized (p) {
                if (p.flag == false) {
                    if (i % 2 == 0) {
                        p.name = "苹果";
                        p.price = 1;
                    } else {
                        p.name = "香蕉";
                        p.price = 2;
                    }
                    System.out.println("唤起消费者,我已生产了" + p.name + "价格" + p.price);
                    p.flag = true;
                    i++;

                    p.notifyAll();
                } else {
                    try {
                        p.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

class Customer implements Runnable{
    Product p;

    public Customer(Product p) {
        this.p = p;
    }

    @Override
    public void run() {
        while(true){
            synchronized (p) {
                if (p.flag == true) {
                    System.out.println("唤起生产者,我消费了" + p.name + "价格" + p.price);
                    p.flag = false;
                    p.notifyAll();
                } else {
                    try {
                        p.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}


public class Test {

    public static void main(String[] args)  {
        Product product = new Product();
        Thread t1 = new Thread(new Producer(product));
        Thread t2 = new Thread(new Customer(product));

        t1.start();
        t2.start();
    }
}    

守护线程

守护线程与普通线程的唯一区别是:当JVM中所有的线程都是守护线程的时候,JVM就可以退出了;如果还有一个或以上的非守护线程则不会退出。(以上是针对正常退出,调用System.exit则必定会退出),所以setDeamon(true)的唯一意义就是告诉JVM不需要等待它退出,让JVM喜欢什么退出就退出吧,不用管它。

class Demo7 extends Thread {

    public Demo7(String name){
        super(name);
    }

    @Override
    public void run() {
        for(int i = 1 ; i<=100 ; i++){
            System.out.println("更新包目前下载"+i+"%");
            if(i==100){
                System.out.println("更新包下载完毕,准备安装..");
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Test {

    public static void main(String[] args)  {
        Demo7 d = new Demo7("后台线程");
        d.setDaemon(true);
        d.start();

        for(int i = 1 ; i<=100 ; i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}    

让我们看下当我把d.setDaemon(true);代码注释与不注释的区别,不注释该代码的话我们会发现两个线程正常执行。 如果注释该代码的话当主线程结束后jvm则直接会退出。

main开始
更新包目前下载1%
main:1
main:2
main:3
main:4
main:5
main:6
main:7
main:8
main:9
更新包目前下载2%
main:10
main:11
main:12
main:13
main:14
main:15
main:16
main:17
main:18
main:19
更新包目前下载3%
main:20
main:21
main:22
main:23
main:24
main:25
main:26
main:27
main:28
main:29
更新包目前下载4%
main:30
main:31
main:32
main:33
main:34
main:35
main:36
main:37
main:38
main:39
更新包目前下载5%
main:40
main:41
main:42
main:43
main:44
main:45
main:46
main:47
main:48
更新包目前下载6%
main:49
main:50
main:51
main:52
main:53
main:54
main:55
main:56
main:57
main:58
更新包目前下载7%
main:59
main:60
main:61
main:62
main:63
main:64
main:65
main:66
main:67
main:68
更新包目前下载8%
main:69
main:70
main:71
main:72
main:73
main:74
main:75
main:76
main:77
更新包目前下载9%
main:78
main:79
main:80
main:81
main:82
main:83
main:84
main:85
main:86
main:87
更新包目前下载10%
main:88
main:89
main:90
main:91
main:92
main:93
main:94
main:95
main:96
main:97
更新包目前下载11%
main:98
main:99
main:100
main结束

线程的停止

线程停止的方法

一:停止一个正常的线程可以通过变量控制

class MyThread extends Thread{
    boolean flag = true;
    @Override
    public void run() {
        int i = 1;
        while (flag){
            System.out.println("正在执行"+i);
            i++;
        }
    }
}




public class Test {

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

        for (int i = 1; i<=100; i++){
            if (i == 80){
                t1.flag = false;
                System.out.println("i=80,t1线程停止");
            }
        }

    }
}

二: 停止一个等待状态下的线程可以通过变量与notify方法合作或interrupt方法与变量合作

注意:把线程的等待状态强制清除,被清除状态的线程会接收到一个InterruptedException。

class MyThread extends Thread{
    boolean flag = true;
    @Override
    public synchronized void run() {
        int i = 1;
        while (flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                System.out.println("接收到了异常了....");
            }
            System.out.println("正在执行"+i);
            i++;
        }
    }
}

public class Test {
    public static void main(String[] args)  {
        MyThread t1 = new MyThread();
        t1.start();

        for(int i = 0 ; i<100 ; i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
            if(i==80){
                t1.flag = false;
                //方式一
                t1.interrupt();//把线程的等待状态强制清除,被清除状态的线程会接收到一个InterruptedException。所以这里线程可以捕捉到异常

                //方式二
                synchronized (t1){
                    t1.notify();
                }
            }
        }
    }
}    

线程的加入

class Production extends Thread{
    @Override
    public synchronized void run() {
        System.out.println("机器启动。。。。");
        System.out.println("机器生产中。。。。");
        System.out.println("机器坏了。。。。");
        Repair r = new Repair();
        r.start();
        try {
            r.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("机器工作了。。。。");
    }
}

class Repair extends Thread{
    @Override
    public synchronized void run() {
        System.out.println("开始修机器。。。。");
        System.out.println("修理中。。。。");
        System.out.println("机器修好了");
    }
}




public class Test {
    public static void main(String[] args)  {
        Production production = new Production();
        production.start();

    }
 }
    

通过上面的列子我门可以发现当一个线程如果执行join语句,那么就有新的线程加入,执行该语句的线程必须要让步给新加入的线程先完成任务,然后才能继续执行。

那么关于当多个线程同时运行时当有其他线程B加入的话,程序会停止所有线程优先执行B吗?其实不是我们看下官网中对该函数的解释:**它的名字表示当前的线程会一直等待,直到加入的线程结束,当前反被唤醒。**让我们看看下面的列子。

class MyThread extends Thread{
    @Override
    public synchronized void run() {
        for (int i = 1; i<=5 ; i++){
            System.out.println(Thread.currentThread().getName()+"执行"+i);
        }
    }

    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }
}



public class Test {

    public static void main(String[] args)  {
        MyThread t1 = new MyThread("A");
        MyThread t2 = new MyThread("B");
        MyThread t3 = new MyThread("C");

        System.out.println("=========="+Thread.currentThread().getName()+"开始");

        System.out.println("==========t1开始==========");
        t1.start();

        System.out.println("==========t2开始==========");
        t2.start();
        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("==========t3开始==========");
        t3.start();

        System.out.println("=========="+Thread.currentThread().getName()+"结束==========");
    }
}

==========main开始
t1开始
t2开始
A执行1
A执行2
B执行1
B执行2
B执行3
A执行3
A执行4
A执行5
B执行4
B执行5
t3开始
main结束
C执行1
C执行2
C执行3
C执行4
C执行5

分析:
发现结果无论怎么样t3线程都是最后执行的,多次实验可以看出t1加入后并不会对加入之前的线程t2有影响,反而是对t3有影响只有t1技术后才可以执行t3。因此,可以得出结论,t1.join()方法只会使主线程进入等待池并等待t1线程执行完毕后才会被唤醒,并不影响同一时刻处在运行状态的其他线程。**它的名字表示当前的线程会一直等待,直到加入的线程结束,当前反被唤醒。**结合这个话看的确如此。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值