案例一

实现一个容器,提供两个方法,add(),count() 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束。
本案例我通过闭锁(也叫门栓锁)实现,实现如下:

package day_12_28.zuoye;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch; /**
* @author soberw
* @Classname AddAndCount
* @Description 实现一个容器,提供两个方法,add,count 写两个线程,
* 线程1添加10个元素到容器中,线程2实现监控元素的个数,
* 当个数到5个时,线程2给出提示并结束。
* @Date 2021-12-28 10:45
*/
public class AddAndCount {
CountDownLatch cdl = new CountDownLatch(1);
List<String> list = new ArrayList<>(); public static void main(String[] args) {
var aac = new AddAndCount();
new Thread(aac::add, "A").start();
new Thread(aac::count, "B").start();
} void add() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
String item = String.format("%s - %d", "item", i);
list.add(item);
System.out.println(Thread.currentThread().getName() + ":" + item);
if (i == 4) {
cdl.countDown();
}
} } void count() {
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("程序结束...");
System.exit(0);
}
}

案例二

编写程序模拟死锁。
死锁,简单来说就是两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
下面我就模拟这一状态:

package day_12_28.zuoye;

/**
* @author soberw
* @Classname Deadlock
* @Description 编写程序模拟死锁
* @Date 2021-12-28 10:59
*/
public class Deadlock {
private final Object o1 = new Object();
private final Object o2 = new Object(); public static void main(String[] args) {
Deadlock d = new Deadlock();
new Thread(d::m1).start();
new Thread(d::m2).start();
} void m1(){
System.out.println(Thread.currentThread().getName() + "启动等待...");
synchronized(o1){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(o2){
System.out.println("哈哈..");
}
}
} void m2(){
System.out.println(Thread.currentThread().getName() + "启动等待...");
synchronized(o2){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(o1){
System.out.println("哈哈..");
}
}
} }

案例三

编写程序,实现三个线程,运行输出 A1 B2 C3 A4 B5 C6 ……
我这里用了两种方式去实现:
方式一:
用公平锁:

package day_12_28.zuoye;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock; /**
* @author soberw
* @Classname TurnNumber
* @Description 编写程序,实现三个线程,运行输出 A1 B2 C3 A4 B5 C6 ….. 用公平锁
* @Date 2021-12-28 14:09
*/
public class TurnNumber {
AtomicInteger num = new AtomicInteger(0);
private final ReentrantLock rl = new ReentrantLock(true); public void show() {
for (; ; ) {
rl.lock();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
String tn = Thread.currentThread().getName();
int i = num.incrementAndGet();
String s = String.format("%s%d", tn, i);
System.out.print(s + " ");
if ("C".equals(tn)) {
System.out.println();
}
rl.unlock();
}
} public static void main(String[] args) throws InterruptedException {
TurnNumber tn = new TurnNumber();
Thread a = new Thread(tn::show, "A");
Thread b = new Thread(tn::show, "B");
Thread c = new Thread(tn::show, "C");
a.setPriority(Thread.MAX_PRIORITY);
a.start();
b.setPriority(Thread.NORM_PRIORITY);
b.start();
c.setPriority(Thread.MIN_PRIORITY);
c.start(); }
}


方式二:
用join() 方法

package day_12_28.zuoye;

import java.util.concurrent.atomic.AtomicInteger;

/**
* @author soberw
* @Classname TurnNumber
* @Description 编写程序,实现三个线程,运行输出 A1 B2 C3 A4 B5 C6 ….. 第二种写法,用join()
* @Date 2021-12-28 14:09
*/
public class TurnNumber2 {
AtomicInteger num = new AtomicInteger(0); public void show() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
String tn = Thread.currentThread().getName();
int i = num.incrementAndGet();
String s = String.format("%s%d", tn, i);
System.out.print(s + " ");
if ("C".equals(tn)) {
System.out.println();
}
} public static void main(String[] args) throws InterruptedException {
TurnNumber2 tn = new TurnNumber2();
while (true) {
Thread a = new Thread(tn::show, "A");
Thread b = new Thread(tn::show, "B");
Thread c = new Thread(tn::show, "C");
a.setPriority(Thread.MAX_PRIORITY);
a.start();
a.join();
b.setPriority(Thread.NORM_PRIORITY);
b.start();
b.join();
c.setPriority(Thread.MIN_PRIORITY);
c.start();
c.join();
} }
}

案例四

创建五个线程并进入等待状态,等两秒后主线程开始并释放全部线程,最后主线程结束

本案例我用的是wait() 与notifyAll()组合形式;

package day_12_27;

import java.util.concurrent.TimeUnit;

/**
* @author soberw
* @Classname WaitAndNotify
* @Description 创建五个线程并进入等待状态,等两秒后主线程开始并释放全部线程,最后主线程结束
* @Date 2021-12-27 15:47
*/
public class WaitAndNotify {
public static void main(String[] args) {
Object co = new Object(); for (int i = 0; i < 5; i++) {
MyThread t = new MyThread("Thread" + i, co);
t.start();
} try {
TimeUnit.SECONDS.sleep(2);
System.out.println("-----Main Thread notify-----");
synchronized (co) {
//co.notify();
co.notifyAll();
} TimeUnit.SECONDS.sleep(2);
System.out.println("Main Thread is end."); } catch (InterruptedException e) {
e.printStackTrace();
}
} static class MyThread extends Thread {
private String name;
private Object co; public MyThread(String name, Object o) {
this.name = name;
this.co = o;
} @Override
public void run() {
System.out.println(name + " is waiting.");
try {
synchronized (co) {
co.wait();
}
System.out.println(name + " has been notified.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

案例五

用五个线程实现,求123456789 之间放±和100的表达式,如果一个线程求出结果,立即告诉其它停止。

这里我用到了AtomicBoolean原子类来保证数据的原子性:

package day_12_27.zuoye;

import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern; /**
* @author soberw
* @Classname Number100
* @Description 用五个线程实现,求123456789 之间放+-和100的表达式,如果一个线程求出结果,立即告诉其它停止。
* @Date 2021-12-27 21:14
*/
public class Number100 {
//原子类,保证原子性
AtomicBoolean ab = new AtomicBoolean(true); public void show() {
String[] ss = {"", "+", "-"};
StringBuilder sbu = new StringBuilder();
sbu.append("1");
Random random = new Random();
while (ab.get()) {
for (int i = 2; i < 9; i++) {
sbu.append(ss[random.nextInt(3)]);
sbu.append(i);
}
Pattern p = Pattern.compile("[0-9]+|-[0-9]+");
Matcher m = p.matcher(sbu.toString());
int sum = 0;
while (m.find()) {
sum += Integer.parseInt(m.group());
}
if (sum == 100) {
ab.set(false);
System.out.println(Thread.currentThread().getName() + ":" + sbu.toString() + " = 100");
}
sbu.delete(1, sbu.length());
}
} public static void main(String[] args) {
var n = new Number100();
for (int i = 0; i < 5; i++) {
new Thread(n::show).start();
}
}
}


案例六

模拟经典问题,生产者-消费者问题:
方式一:

package day_12_28.zuoye;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* @author soberw
* @Classname ProductorAndConsumerForLock
* @Description 用线程通信机制解决生产者消费者问题
* @Date 2021-12-28 19:18
*/
public class ProductorAndConsumerForLock { public static void main(String[] args) {
Clerk1 clerk1 = new Clerk1(); Productor1 pro = new Productor1(clerk1);
Consumer1 con = new Consumer1(clerk1); new Thread(pro, "生产者 A").start();
new Thread(con, "消费者 B").start(); // new Thread(pro, "生产者 C").start();
// new Thread(con, "消费者 D").start();
} } class Clerk1 {
private int product = 0; private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition(); // 进货
public void get() {
lock.lock(); try {
if (product >= 1) { // 为了避免虚假唤醒,应该总是使用在循环中。
System.out.println("产品已满!"); try {
condition.await();
} catch (InterruptedException e) {
} }
System.out.println(Thread.currentThread().getName() + " : "
+ ++product); condition.signalAll();
} finally {
lock.unlock();
} } // 卖货
public void sale() {
lock.lock(); try {
if (product <= 0) {
System.out.println("缺货!"); try {
condition.await();
} catch (InterruptedException e) {
}
} System.out.println(Thread.currentThread().getName() + " : "
+ --product); condition.signalAll(); } finally {
lock.unlock();
}
}
} // 生产者
class Productor1 implements Runnable { private Clerk1 clerk1; public Productor1(Clerk1 clerk1) {
this.clerk1 = clerk1;
} @Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
} clerk1.get();
}
}
} // 消费者
class Consumer1 implements Runnable { private Clerk1 clerk1; public Consumer1(Clerk1 clerk1) {
this.clerk1 = clerk1;
} @Override
public void run() {
for (int i = 0; i < 20; i++) {
clerk1.sale();
}
} }

方式二

package day_12_28.zuoye;

/**
* @author soberw
* @Classname ProducerAndConsumer
* @Description 用等待唤醒机制解决生产者消费者问题
* @Date 2021-12-28 16:25
*/
public class ProductorAndConsumer { public static void main(String[] args) {
Clerk clerk = new Clerk(); Productor pro = new Productor(clerk);
Consumer cus = new Consumer(clerk); new Thread(pro, "生产者 A").start();
new Thread(cus, "消费者 B").start(); new Thread(pro, "生产者 C").start();
new Thread(cus, "消费者 D").start();
} } //店员
class Clerk {
private int product = 0; //进货
public synchronized void get() {//循环次数:0
//为了避免虚假唤醒问题,应该总是使用在循环中
while (product >= 1) {
System.out.println("产品已满!"); try {
this.wait();
} catch (InterruptedException e) {
} } System.out.println(Thread.currentThread().getName() + " : " + ++product);
this.notifyAll();
} //卖货
public synchronized void sale() {//product = 0; 循环次数:0
while (product <= 0) {
System.out.println("缺货!"); try {
this.wait();
} catch (InterruptedException e) {
}
} System.out.println(Thread.currentThread().getName() + " : " + --product);
this.notifyAll();
}
} //生产者
class Productor implements Runnable {
private Clerk clerk; public Productor(Clerk clerk) {
this.clerk = clerk;
} @Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
} clerk.get();
}
}
} //消费者
class Consumer implements Runnable {
private Clerk clerk; public Consumer(Clerk clerk) {
this.clerk = clerk;
} @Override
public void run() {
for (int i = 0; i < 20; i++) {
clerk.sale();
}
}
}

案例七

开十个线程打印输出1~10000中偶数的值,计算总耗时
我采用的是闭锁机制:

package day_12_28.zuoye;

import java.util.concurrent.CountDownLatch;

/**
* @author soberw
* @Classname CountTime
* @Description 开十个线程打印输出1~10000中偶数的值,计算总耗时 用闭锁(门栓)
* @Date 2021-12-28 15:22
*/
public class CountTime {
static CountDownLatch cdl = new CountDownLatch(10); void show() {
for (int i = 0; i < 10000; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
cdl.countDown();
} public static void main(String[] args) {
CountTime ct = new CountTime();
long start = System.currentTimeMillis();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 10; i++) {
new Thread(ct::show).start();
}
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println((end - start - 100) + "--------------");
}
}

最新文章

  1. Javascript练习
  2. 简单的 JSON 对象进行深拷贝最简单的方法
  3. How a woman&#39;s glance can tell a man if she&#39;s interested
  4. 关于delphi Assigned
  5. html页面布局 第8节
  6. Java Timer 定时器的使用
  7. 《javascript dom编程艺术》笔记(一)——优雅降级、向后兼容、多个函数绑定onload函数
  8. ajax文本空输入显示用户信息
  9. Django 模板.html中 href参数传入
  10. 给hMailServer添加DKIM图文教程
  11. 集合之TreeSet(含JDK1.8源码分析)
  12. 实战ELK(7)ElasticSearch常用的基本查询语句
  13. 如何参与linux内核开发
  14. Win10更改CMD控制台的代码页和字体和字号
  15. j.u.c系列(05)---之重入锁:ReentrantLock
  16. Android中的Service 与 Thread 的区别[转]
  17. sparkr基本操作1
  18. 将数据提取到CSV文件中保存
  19. 如何快速简单粗暴地理解Python中的if __name__ == &#39;__main__&#39;
  20. SQL Server 数据收缩

热门文章

  1. 初识python:time 模版
  2. nuxt写路由接口
  3. Echart可视化学习(二)
  4. 通过js触发onPageView和event事件获取页面信息
  5. 软件开发架构与网络之OSI七层协议(五层)
  6. 《剑指offer》面试题03. 数组中重复的数字
  7. 短视频正当时,如何让你的App快速构建视频创作能力?
  8. Servlet Cookie的使用
  9. IDEA导入建立图标类型的包失败
  10. 基于paddlepaddle的人像抠图程序