Day18_进程(中)

Day18_进程(中)

常用的一些方法

join():半路杀出程咬金

sleep(1000):线程停止1000ms。

yield():暂停当前线程,使当前线程转入就绪阶段

stop():过期方法

伴随线程

public class Bansui extends Thread{
    @Override
    public void run() {
        for (int i = 1; i <=1000 ; i++) {
            System.out.println("Bansui----"+i);
        }
    }

    public static void main(String[] args) {
        for (int i = 1; i <=10 ; i++) {
            if(i==6){
                Bansui bs=new Bansui();
                //设置伴随线程,参数设置为true,实现"同生共死",但是两个线程停止时间点会有时间间隔
                bs.setDaemon(true);
                bs.start();
            }
            System.out.println("main---"+i);
        }
    }
}

输出

main---1
main---2
main---3
main---4
main---5
main---6
main---7
main---8
main---9
Bansui----1
main---10
Bansui----2
Bansui----3
Bansui----4
Bansui----5
Bansui----6
Bansui----7
Bansui----8
Bansui----9
Bansui----10
Bansui----11
Bansui----12
Bansui----13

线程的同步

加锁

同步代码块

public class Ticket implements Runnable{
    private int ticketNum=10;
    @Override
    public void run() {
        for (int i = 1; i <=100; i++) {
          //同步代码块
          //加锁
            synchronized (Ticket.class){
                if(ticketNum>0){
                    System.out.println("我在"+Thread.currentThread().getName()+"买到了剩余的第"+ticketNum--+"张火车票!");
                }
            }
        }
    }
}
public class ticketTest {
    public static void main(String[] args) {
        Ticket tk=new Ticket();
        Thread t1=new Thread(tk,"窗口1");
        t1.start();
        Thread t2=new Thread(tk,"窗口2");
        t2.start();
        Thread t3=new Thread(tk,"窗口3");
        t3.start();
    }
}

输出:

我在窗口1买到了剩余的第10张火车票!
我在窗口1买到了剩余的第9张火车票!
我在窗口1买到了剩余的第8张火车票!
我在窗口1买到了剩余的第7张火车票!
我在窗口1买到了剩余的第6张火车票!
我在窗口1买到了剩余的第5张火车票!
我在窗口1买到了剩余的第4张火车票!
我在窗口1买到了剩余的第3张火车票!
我在窗口1买到了剩余的第2张火车票!
我在窗口1买到了剩余的第1张火车票!

同步方法

public class Ticket implements Runnable{
    private int ticketNum=10;
    @Override
    public void run() {
        for (int i = 1; i <=100 ; i++) {
            buy();
        }
    }
  //同步方法
    public synchronized void buy(){
        if(ticketNum>0){
            System.out.println("我在"+Thread.currentThread().getName()+"买到了剩余的第"+ticketNum--+"张火车票!");
        }
    }
}
public class ticketTest {
    public static void main(String[] args) {
      //同一个tk对象,所以一把锁即可实现同步
        Ticket tk=new Ticket();
        Thread t1=new Thread(tk,"窗口1");
        t1.start();
        Thread t2=new Thread(tk,"窗口2");
        t2.start();
        Thread t3=new Thread(tk,"窗口3");
        t3.start();
    }
}
我在窗口1买到了剩余的第10张火车票!
我在窗口1买到了剩余的第9张火车票!
我在窗口1买到了剩余的第8张火车票!
我在窗口1买到了剩余的第7张火车票!
我在窗口1买到了剩余的第6张火车票!
我在窗口1买到了剩余的第5张火车票!
我在窗口3买到了剩余的第4张火车票!
我在窗口3买到了剩余的第3张火车票!
我在窗口3买到了剩余的第2张火车票!
我在窗口3买到了剩余的第1张火车票!

总结

synchronized

  1. 必须是引用数据类型,不能是基本数据类型
  2. 在同步代码块中可以改变同步监视器对象的值,不能改变其引用
  3. 尽量不要String和包装类Integer做同步监视器。如果使用了,只要保证代码块不对其进行任何操作也没关系
  4. 一般使用共享资源做同步监视器即可
  5. 也可以创建一个专门的同步监视器,没有任何业务含义
  6. 建议使用final修饰同步监视器

同步代码块的执行过程

  1. 第一个线程来到同步代码块,发现同步监视器open状态,需要close,然后执行其中的代码
  2. 第一个线程执行过程中,发生了线程切换(阻塞 就绪),第一个线程失去CPU,但是没有开锁open
  3. 第二个线程获取了CPU,来到了同步代码块,发现同步监视器close状态,无法执行其中的代码,第二个线程也进入阻塞状态
  4. 第一个线程再次获取了CPU,接着执行了后续的代码,同步代码块执行完毕,释放锁open
  5. 第二个线程也再次获取CPU,来到了同步代码块,发现同步监视器open状态,重复第一个线程的处理过程(加锁)。强调:同步代码块中能发生线程切换吗?能!!但是后续的被执行的线程也无法执行同步代码块(锁仍旧close;

线程同步优缺点

优点:安全

缺点:效率低下,可能出现死锁

第三种加锁方式Lock

Lock lock=new ReentrantLock();
//加锁
lock.lock();
try{
  //要锁的代码
}finally{
  //解除锁
  lock.unlock();
}

Lock更加灵活,但是只能使用同步块,不能用同步方法。

线程的通信

锁池:synchronized

等待池:wait(),notify(),notifyAll()

如果一个线程调用了某个对象的wait()方法,那么该线程进入到该对象的等待池中(并且已经将锁释放),如果未来的某个时刻,另外一个线程调用了相同对象的notify方法或者notifyAll方法,那么该等待池中的线程就会被唤起,然后进入到对象的锁池里面去获得该对象的锁,如果获得锁成功后,那么该线程就会沿着wait方法之后的语句继续执行,注意是沿着wait方法之后的语句继续执行。

public class Shangpin {
    private String name;
    private String brand;
    //信号灯
    boolean flag=false;
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    //生产者
    public synchronized void setSp(String brand,String name){
        //有商品,生产者等待
        if(flag){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        this.setBrand(brand);
        this.setName(name);
        System.out.println("生产者生产了"+this.getBrand()+"---"+this.getName());
        //生产出来了,通知消费者来取产品
        flag=true;
        notify();
    }
    //消费者
    public synchronized void getSp() {
        //无商品,消费者等待
        if (!flag) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("消费者消费了" + this.getBrand() + "---" + this.getName());
        //消费者取完产品,通知生产者生产
        flag = false;
        notify();
    }
}
public class Shengchanzhe implements Runnable {
    private Shangpin sp;

    public Shengchanzhe(Shangpin sp) {
        this.sp = sp;
    }

    @Override
    public void run() {
        //为什么要加for循环,因为要生产10个商品,每生产一个商品,就会停下来等待消费者消费商品
        //可以尝试把消费者中的for循环删除,如果能解释结果,就说明对线程的运行有所了解了
        //原因是:没加for循环时,消费者只消费了一次,所以线程就停在那里了
        for (int i = 1; i <=10 ; i++) {
            if(i%2==0){
                sp.setSp("DOVE","chocolate");
            }else{
                sp.setSp("青岛","啤酒");
            }
        }
    }
}
public class Xiaofeizhe implements Runnable{
    private Shangpin sp;

    public Xiaofeizhe(Shangpin sp) {
        this.sp = sp;
    }

    @Override
    public void run() {
        for (int i = 1; i <=10 ; i++) {
            sp.getSp();
        }
    }
}
public class ShangpinTest {
    public static void main(String[] args) {
        Shangpin sp=new Shangpin();
        Shengchanzhe scz=new Shengchanzhe(sp);
        new Thread(scz).start();

        Xiaofeizhe xfz=new Xiaofeizhe(sp);
        new Thread(xfz).start();
    }
}

输出

生产者生产了青岛---啤酒
消费者消费了青岛---啤酒
生产者生产了DOVE---chocolate
消费者消费了DOVE---chocolate
生产者生产了青岛---啤酒
消费者消费了青岛---啤酒
生产者生产了DOVE---chocolate
消费者消费了DOVE---chocolate
生产者生产了青岛---啤酒
消费者消费了青岛---啤酒
生产者生产了DOVE---chocolate
消费者消费了DOVE---chocolate
生产者生产了青岛---啤酒
消费者消费了青岛---啤酒
生产者生产了DOVE---chocolate
消费者消费了DOVE---chocolate
生产者生产了青岛---啤酒
消费者消费了青岛---啤酒
生产者生产了DOVE---chocolate
消费者消费了DOVE---chocolate
原文地址:https://www.cnblogs.com/gaoyao/p/13624570.html