多线程基础(六)

2019-03-10  本文已影响0人  Maxinxx

之前的思路会导致一个问题:
A:如果消费者先抢到了CPU的执行权,就会去消费数据,但是现在的数据是默认值,没有意义,应该等到数据有意义,再去消费。
B:如果生产者先抢到CPU的执行权,就会去产生数据,但是,它产生完数据之后,还继续拥有执行权,它会继续产生数据。这是有问题的,应该等到消费者把数据消费掉,然后再生产。

正常的思路:
A(生产者):先看是否有数据,有就等待,没有就生产,生产完之后通知消费者来消费数据。
B(消费者):先看是否有数据,有就消费,没有就等待,通知生产者生产数据。

为了处理这样的问题,Java就提供了一种机制:等待唤醒机制。

等待唤醒机制

等待唤醒:
Object类中提供了三个方法:

wait():等待
notify():唤醒单个线程
notifyAll():唤醒所有线程

为什么这些方法不定义在Thread类中呢:
回答:因为这些方法的调用必须通过锁对象调用,而我们刚才使用的锁对象是任意锁对象,所以这些方法必须定义在Object类中。

public class Student {
    String name;
    int age;
    boolean flag = false;//默认情况是false,没有数据
}
public class SetThread implements Runnable {
    private Student s;
    private int x = 0;
    
    public SetThread(Student s) {
        this.s =s;
    }

    @Override
    public void run() {
        while(true) {
            synchronized (s) {
                //判断有没有
                if(s.flag) {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if(x % 2 == 0) {
                    s.name = "娇娇";
                    s.age = 22;
                }else {
                    s.name = "昕昕";
                    s.age = 23;
                }
                x++;
                
                //修改标记
                s.flag = true;
                s.notify();
            }
        }
    }
}
public class GetThread implements Runnable {
    private Student s;

    public GetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (s) {
                if(!s.flag) {
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(s.name + "---" + s.age);
                
                s.flag = false;
                s.notify();
            }
        }
    }
}

线程组

线程组:把多个线程组合到一起
它可以对一批线程进行分类管理,Java允许程序直接对线程进行控制。

  1. 得到线程的线程组:public final ThradGroup getThreadGroup()
  2. 创造线程(参数带有线程组):Thread(ThreadGroup group, Runnable target, String name)
  1. 得到该线程组的名字:public final String getName()
  2. 创建一个线程组(构造方法):ThreadGroup(String name)
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}
public class ThreadGroupDemo {
    public static void main(String[] args) {
        MyRunnable mr = new MyRunnable();
        
        Thread t1 = new Thread(mr, "娇娇");
        Thread t2 = new Thread(mr, "昕昕");
        
        ThreadGroup tg1 = t1.getThreadGroup();
        ThreadGroup tg2 = t2.getThreadGroup();
        
        String name1 = tg1.getName();
        String name2 = tg2.getName();
        
        System.out.println(name1);
        System.out.println(name2);
        //通过结果知道:线程默认情况下属于main线程组
        
        System.out.println(Thread.currentThread().getThreadGroup().getName());
        //通过结果知道:默认情况下,所有的线程都属于同一个组
    }
}
public class ThreadGroupDemo {
    public static void main(String[] args) {
        ThreadGroup tg = new ThreadGroup("这是一个新的组");
        
        MyRunnable mr = new MyRunnable();
        Thread t1 = new Thread(tg, mr, "娇娇");
        Thread t2 = new Thread(tg, mr, "昕昕");
        
        System.out.println(t1.getThreadGroup().getName());
        System.out.println(t2.getThreadGroup().getName());
    }
}

线程池

程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互,而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。

  1. public static ExecutorsService newCachedThreadPool():开启具有缓存功能的线程池
  2. public static ExecutorService newFixedThreadPool(int nThreads):创建具有指定数量线程的线程池
  3. public static ExcutorService newSingleThreadExecutor():创建一个具有一个线程的线程池
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}
public class ExecutorsDemo {
    public static void main(String[] args) {
        //创建一个线程池对象,控制要创建几个线程对象。
        ExecutorService pool = Executors.newFixedThreadPool(2);
        
        pool.submit(new MyRunnable());
        pool.submit(new MyRunnable());
        
        pool.shutdown();
    }
}
上一篇 下一篇

猜你喜欢

热点阅读