针对同一个资源的操作有不同种类的线程,让不同的线程相互影响且不发生错乱,即我们常说的生产者消费者模式。
生产者消费者问题,也称有限缓冲问题,是一个多线程同步问题的经典案例,该问题描述了两个共享固定大小缓冲区的线程——即生产者和消费者——在运行时会出现的问题。
生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程,与此同时,消费者也在缓冲区消耗这些数据,该问题的关键就是要保证生产者不会在缓冲区满是加入数据,消费者也不会在缓冲区空时消耗数据。
通过设置线程(生产者)和获取线程(消费者)针对同一个学生对象进行操作。
代码
public class Student {
String name;
int age;
boolean flag=true;//信号灯法,用来标志是否已经录入信息
}
/**
* wait();使线程进入等待状态————阻塞状态
* notify();唤醒线程————就绪状态
*/
public class SetStudent implements Runnable {
Student s = new Student();
public SetStudent(Student s) {
this.s = s;
}
@Override
public void run() {
while (true) {
synchronized (s) {
if(s.flag) {//代表学生信息已经录入,需要消费者消费
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
s.name="张三";
s.age=17;
s.flag=true;//修改标记
s.notify();//唤醒因为s锁对象进入等待状态的线程---获取线程
}
}
}
}
public class GetStudent implements Runnable {
Student s= new Student();
public GetStudent(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();//唤醒因为s所对象进入等待状态的线程---设置线程
}
}
}
}
/*
* 资源类:Student
* 设置线程:SetStudent
* 获取线程:GetStudent
* 测试类:StudentDemo
*
*/
public class StudentDemo {
public static void main(String[] args) {
Student s = new Student();
SetStudent set = new SetStudent(s);
GetStudent get = new GetStudent(s);
Thread t1 = new Thread(set);
Thread t2 = new Thread(get);
t1.start();
t2.start();
}
}
1、线程组
Java中使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。
默认情况下,所有的线程都属于主线程组。
public final ThreadGroup getThreadGroup()我们也可以给线程设置分组
Thread(ThreadGroup group, Runnable target, String name)
2、线程池
程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,
尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。
线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
在JDK5之前,我们必须手动实现自己的线程池,从JDK5开始,Java内置支持线程池。
JDK5新增了一个Executors工厂类来产生线程池,有如下几个方法
public static ExecutorService newCachedThreadPool()
public static ExecutorService newFixedThreadPool(int nThreads)
public static ExecutorService newSingleThreadExecutor()这些方法的返回值是ExecutorService对象,该对象表示一个线程池,可以执行Runnable对象或者Callable对象代表的
线程。
它提供了如下方法
Future> submit(Runnable task)