1.三种线程按顺序执行
public class Test1 {
// private static Logger log = Logger.getLogger(Test2.class);
public static void main(String[] args) throws InterruptedException {
//创建三个线程按照线程a,b,c执行
Thread a = new PrintThread();
Thread b = new PrintThread();
Thread c = new PrintThread();
a.setName("Thread-a");
b.setName("Thread-b");
c.setName("Thread-c");
a.start();
a.join();
b.start();
b.join();
c.start();
c.join();
}
public static class PrintThread extends Thread{
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName());
}
}
}
按序打印
通过join()方法使得哪个线程调用join()方法,哪个线程执行完才能执行后续线程
2.两个线程轮流打印数字,直到100
public class Test2 {
private static final Object lock = new Object();
private static int count = 0;
public static void main (String[] args) {
//满足条件进入计算,可使得其他线程满足计算后的条件,不满足则等待
new Thread(new PrintThread(0), "a").start();
new Thread(new PrintThread(1), "b").start();
}
static class PrintThread implements Runnable{
private int threadId;
private PrintThread(int threadId){
this.threadId = threadId;
}
@Override
public void run() {
synchronized (lock){
while(count <= 100){
if(count%2 == threadId){//条件判断,结合wait和notifyAll
log.info(Thread.currentThread().getName()+"------"+count);
count++;
lock.notifyAll();
}else{
try {
lock.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
}
}
}
数字交替打印
通过加锁的方式保证线程同步访问共享资源,通过条件变量调用notifyAll()方法获取锁通知线程执行,调用wait方法释放锁进入等待状态
3.交替打印ABC
public class Test3 {
public static void main(String[] args) {
AwaitSignal as = new AwaitSignal(5);
//休息室
Condition a = as.newCondition();
Condition b = as.newCondition();
Condition c = as.newCondition();
//
new Thread(() -> {
as.print("A", a, b);
}).start();
new Thread(() -> {
as.print("B", b, c );
}).start();
new Thread(() -> {
as.print("C", c, a);
}).start();
as.lock();
try{
System.out.println("开始...");
a.signal();//需要主线程主动唤醒a线程
}finally {
as.unlock();
}
}
//
static class AwaitSignal extends ReentrantLock {
private int loopNumber;
public AwaitSignal(int loopNumber){
this.loopNumber = loopNumber;
}
//参数1 打印内容,参数2 当前休息室,参数3:下一间休息室
public void print(String str, Condition current, Condition next){
for (int i = 0; i < loopNumber; i++) {
lock();//继承ReentrantLock锁手动加锁,锁住一个休息室
try {
current.await();//休息室等待
System.out.print(str);
next.signal();//进入下一个休息室
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
unlock();
}
}
}
}
}
交替打印ABC
通过继承ReentrantLock类来对字符按照顺序打印,其中包含两个Condition(休息等待区),一个当前Condition,另一个下一个Condition。只有前一个执行完后通过notifyAll()方法获取锁通知下一个进行。
4.生产者消费者模式
public class Test4 {
Logger logger = LoggerFactory.getLogger(ProducerAndCustomerTest.class);
public static void main(String[] args) {
MessageQueue queue = new MessageQueue(2);
//创建三个生产者生产消息
for (int i = 0; i < 3 ; i++) {
int id = i;
new Thread(() ->{
queue.put(new Message(id, "值:"+id));
}, "生产者" + i).start();
}
new Thread(() -> {
while(true){
try {
Thread.sleep(1);
queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"消费者").start();
}
}
//消息队列类,java线程之间通信
class MessageQueue{
Logger logger = LoggerFactory.getLogger(MessageQueue.class);
//消息队列集合
private LinkedList<Message> list = new LinkedList<>();
//队列容量
private int capacity;
public MessageQueue(int capacity) {
this.capacity = capacity;
}
//获取消息
public Message take(){
//检查对象是否为null
synchronized (list){
while(list.isEmpty()){
try {
logger.info("队列为空,消费者等待消息生产");
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//从队列头部获取消息返回
Message message = list.removeFirst();
logger.info("已消费信息 {}", message);
//消费完通知
list.notifyAll();
return message;
}
}
//存入消息
public void put(Message message){
synchronized (list){
//检查队列是否已满
while (list.size() == capacity){
try {
logger.info("队列已满,生产者线程等待");
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//将消息加入队列尾部
list.addLast(message);
logger.info("已生产信息 {}", message);
list.notifyAll();//生产完通知
}
}
}
final class Message{//安全
private int id;
private Object value;
public Message(int id, Object value) {
this.id = id;
this.value = value;
}
public int getId() {//只有读安全,无法改变值
return id;
}
public Object getValue() {
return value;
}
@Override
public String toString() {
return "Message{" +
"id=" + id +
", value=" + value +
'}';
}
}
提供者和消费者模式
创建两类线程,一类生产者线程,另一类消费者线程。通过生产者线程生产消息并加入消息队列中,另一类消费者线程从消息队列中取出消息消费。通过消息队列的take()判断当消息集合为空时调用wait等待生产者生产,不为空时从消息集合取消息,并通过notifyAll()方法通知生产者消息消费完。通过消息队列的put()判断当消息集合为满时调用wait等待消费者,不满时向消息集合加入消息,并通过notifyAll()方法通知生产者消费消息。