多线程详解(狂神说)
线程,进程,多线程
线程创建
[](https://imgtu.com/i/20km4K)
继承Thread类
网图下载
package th.demo01;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* @Author 天红
* @Date 2021/6/7 20:04
* @Version 1.0
*/
//练习Thread,实现多线程同步下载图片
public class TestThread1 extends Thread{
private String url;
private String name;
public TestThread1(String url, String name) {
this.url = url;
this.name = name;
}
// 下载图片线程的执行体
@Override
public void run() {
WebDownLLoader webDownLLoader = new WebDownLLoader();
webDownLLoader.downLoad(url,name);
System.out.println("下载了文件名为:"+name);
}
public static void main(String[] args) {
TestThread1 t1 = new TestThread1("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2F1114%2F0G520141919%2F200G5141919-2-1200.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=47d43ca821a757183016d42c33ec8b41","1.jpg");
TestThread1 t2 = new TestThread1("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fclubimg.club.vmall.com%2Fdata%2Fattachment%2Fforum%2F202004%2F28%2F232538icfogvlsgjywjw36.jpg&refer=http%3A%2F%2Fclubimg.club.vmall.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=0b38b8beab9576e4a06f51f6c81c70a5","2.jpg");
TestThread1 t3 = new TestThread1("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201603%2F04%2F20160304192803_HRdrS.thumb.700_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660908&t=1a2a2fb9358036ee12f43e25b1e3564f","3.jpg");
t1.start();
t2.start();
t3.start();
}
}
//下载器
class WebDownLLoader{
// 下载方法
public void downLoad(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO异常");
}
}
}
实现Runnable接口
package th.demo01;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* @Author 天红
* @Date 2021/6/7 20:04
* @Version 1.0
*/
//练习Thread,实现多线程同步下载图片
public class TestThread1 implements Runnable{
private String url;
private String name;
public TestThread1(String url, String name) {
this.url = url;
this.name = name;
}
// 下载图片线程的执行体
@Override
public void run() {
WebDownLLoader webDownLLoader = new WebDownLLoader();
webDownLLoader.downLoad(url,name);
System.out.println("下载了文件名为:"+name);
}
public static void main(String[] args) {
TestThread1 t1 = new TestThread1("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2F1114%2F0G520141919%2F200G5141919-2-1200.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=47d43ca821a757183016d42c33ec8b41","1.jpg");
TestThread1 t2 = new TestThread1("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fclubimg.club.vmall.com%2Fdata%2Fattachment%2Fforum%2F202004%2F28%2F232538icfogvlsgjywjw36.jpg&refer=http%3A%2F%2Fclubimg.club.vmall.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=0b38b8beab9576e4a06f51f6c81c70a5","2.jpg");
TestThread1 t3 = new TestThread1("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201603%2F04%2F20160304192803_HRdrS.thumb.700_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660908&t=1a2a2fb9358036ee12f43e25b1e3564f","3.jpg");
new Thread(t1).start();
new Thread(t2).start();
new Thread(t3).start();
}
}
//下载器
class WebDownLLoader{
// 下载方法
public void downLoad(String url,String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO异常");
}
}
}
小节
####
初始并发问题
买火车票例子
package th.demo01;
/**
* @Author 天红
* @Date 2021/6/7 21:01
* @Version 1.0
*/
//多个线程操作同一个对象
// 买火车的例子
// 发现问题:多个线程操作同一个资源的情况下,线程不安全,数据紊乱
public class TestThread2 implements Runnable {
private int ticketNums=10;
@Override
public void run() {
while (true){
if (ticketNums<=0){
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"票");
}
}
public static void main(String[] args) {
TestThread2 ticket = new TestThread2();
new Thread(ticket,"天红").start();
new Thread(ticket,"老婆").start();
new Thread(ticket,"牛").start();
}
}
龟兔赛跑
package th.demo01;
/**
* @Author 天红
* @Date 2021/6/7 21:29
* @Version 1.0
*/
public class Race implements Runnable{
// 胜利者
private static String winner;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
// 模拟兔子休息
if (Thread.currentThread().getName().equals("兔子")&&i%10==0){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 判断比赛是否结束
boolean flag=gameOver(i);
if (flag){
break;
}
System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步");
}
}
// 判断是否完成比赛
private boolean gameOver(int steps){
if (winner!=null){
return true;
}{
if (steps>=100){
winner=Thread.currentThread().getName();
System.out.println("winner is"+winner);
return true;
}
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race,"兔子").start();
new Thread(race,"乌龟").start();
}
}
实现Callable接口(了解即可)
package th.demo01;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;
/**
* @Author 天红
* @Date 2021/6/8 19:40
* @Version 1.0
*/
//callable的好处
//1,可以定义返回值
//2,可以抛出异常
public class TestCallable implements Callable<Boolean> {
private String url;
private String name;
public TestCallable(String url, String name) {
this.url = url;
this.name = name;
}
// 下载图片线程的执行体
@Override
public Boolean call() {
WebDownLLoader webDownLLoader = new WebDownLLoader();
webDownLLoader.downLoad(url, name);
System.out.println("下载了文件名为:" + name);
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
TestCallable t1 = new TestCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2F1114%2F0G520141919%2F200G5141919-2-1200.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=47d43ca821a757183016d42c33ec8b41", "1.jpg");
TestCallable t2 = new TestCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fclubimg.club.vmall.com%2Fdata%2Fattachment%2Fforum%2F202004%2F28%2F232538icfogvlsgjywjw36.jpg&refer=http%3A%2F%2Fclubimg.club.vmall.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660613&t=0b38b8beab9576e4a06f51f6c81c70a5", "2.jpg");
TestCallable t3 = new TestCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201603%2F04%2F20160304192803_HRdrS.thumb.700_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625660908&t=1a2a2fb9358036ee12f43e25b1e3564f", "3.jpg");
// 创建执行服务
ExecutorService service = Executors.newFixedThreadPool(3);
// 提交执行
Future<Boolean> r1 = service.submit(t1);
Future<Boolean> r2 = service.submit(t2);
Future<Boolean> r3 = service.submit(t3);
boolean res1 = r1.get();
boolean res2 = r1.get();
boolean res3 = r1.get();
System.out.println(res1);
System.out.println(res2);
System.out.println(res3);
// 关闭服务
service.shutdown();
}
//下载器
class WebDownLLoader {
// 下载方法
public void downLoad(String url, String name) {
try {
FileUtils.copyURLToFile(new URL(url), new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO异常");
}
}
}
}
静态代理模式
package th.demo01;
/**
* @Author 白天红
* @Date 2021/6/8 20:13
* @Version 1.0
*/
//静态代理模式总结:
// 真实对象和代理对象都要实现同一个接口
// 代理角色要代理真实角色
// 好处
//代理对象可以做真实对象做不了的事情
//真实对象专注做自己的事情
public class StaticProxy {
public static void main(String[] args) {
new Thread(()-> System.out.println("我爱你")).start();
// 是不是一样,线程底部就用了静态代理模式
new WeddingCompany(new You()).happyMarry();
}
}
interface Marry{
void happyMarry();
}
//真实角色,你去结婚
class You implements Marry{
@Override
public void happyMarry() {
System.out.println("天红要结婚了,开心😍");
}
}
//代理角色,帮助你去结婚
class WeddingCompany implements Marry{
// 代理谁--》真是目标角色
private Marry target;
public WeddingCompany(Marry target) {
this.target = target;
}
@Override
public void happyMarry() {
before();
this.target.happyMarry();//这就是真实对象
after();
}
private void after() {
System.out.println("结婚之后,收尾款");
}
private void before() {
System.out.println("结婚之前,布置现场");
}
}
Lambda表达式
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/10 15:39
* @Version 1.0
*/
//推导Lambda表达式
public class TestLambda01 {
// 3.静态内部类
static class Like2 implements ILike{
@Override
public void Lambda() {
System.out.println("I like yan2");
}
}
public static void main(String[] args) {
ILike like=new Like();
like.Lambda();
like=new Like2();
like.Lambda();
//4.局部类部类
class Like3 implements ILike{
@Override
public void Lambda() {
System.out.println("I like yan3");
}
}
like=new Like3();
like.Lambda();
//5.匿名内部类,没有类的名字,必须借助接口或者父类
like=new ILike() {
@Override
public void Lambda() {
System.out.println("I like yan4");
}
};
like.Lambda();
//用lambda简化
like=() ->{
System.out.println("I like yan5");
};
like.Lambda();
}
}
//1.定义一个接口
interface ILike{
void Lambda();
}
//2.定义一个实现类
class Like implements ILike{
@Override
public void Lambda() {
System.out.println("I like yan");
}
}
线程状态
五大状态
线程停止举例
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/10 17:27
* @Version 1.0
*/
public class TestStop implements Runnable{
private boolean flag=true;
@Override
public void run() {
int i=0;
while (flag){
System.out.println("run.....Thread"+i++);
}
}
public void stop(){
flag=false;
}
public static void main(String[] args) {
TestStop t1=new TestStop();
new Thread(t1).start();
for (int i = 0; i < 100; i++) {
System.out.println("mian"+i);
if (i==99){
t1.stop();
System.out.println("线程该停止啦~");
}
}
}
}
线程休眠
模拟网络延迟
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/10 17:47
* @Version 1.0
*/
//多个线程操作同一个对象
// 买火车的例子
// 发现问题:多个线程操作一个资源的情况下,线程不安全,数据紊乱
// 模拟网络延迟,放大问题的的发生性
public class TestSleep implements Runnable {
private int ticketNums=10;
@Override
public void run() {
while (true){
if (ticketNums<=0){
break;
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"票");
}
}
public static void main(String[] args) {
TestSleep ticket = new TestSleep();
new Thread(ticket,"天红").start();
new Thread(ticket,"老婆").start();
new Thread(ticket,"牛").start();
}
}
模拟倒计时
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/10 17:57
* @Version 1.0
*/
//模拟倒计时
public class TestSleep2 {
public static void main(String[] args) {
try {
tenDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void tenDown() throws InterruptedException {
int num=10;
while (true){
Thread.sleep(1000);
System.out.println(num--);
if (num<0){
break;
}
}
}
}
打印倒计时
package TestLambda;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Author 天红
* @Date 2021/6/10 18:05
* @Version 1.0
*/
//打印倒计时
public class TestSleep3 {
public static void main(String[] args) {
// 打印当前系统时间
Date date = new Date(System.currentTimeMillis());
System.out.println(System.currentTimeMillis());
System.out.println(date);
while (true){
try {
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
date = new Date(System.currentTimeMillis()); //更新当前时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程礼让(yield)
join合并线程
线程状态观测(五个)
线程状态举例
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/10 19:55
* @Version 1.0
*/
public class TestState {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("=============");
});
//观察状态
Thread.State state = thread.getState();
System.out.println(state);
System.out.println("#########");
//观察启动后
thread.start(); //启动线程
state=thread.getState();
System.out.println(state); //运行
while (state!=Thread.State.TERMINATED){
Thread.sleep(1000);
state=thread.getState(); //更新线程状态
System.out.println(state); //输出状态
}
}
}
线程的优先级
守护线程(daemon)
概念
守护线程测试
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/10 21:38
* @Version 1.0
*/
public class TestDaemon {
public static void main(String[] args) {
You you = new You();
God god = new God();
Thread thread = new Thread(god);
thread.setDaemon(true); //默认flase表示守护线程
thread.start(); //上帝,守护线程启动
new Thread(you).start(); //你 用户线程启动
}
}
class You implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("你在开心的活着第"+i+"天");
}
System.out.println("===拜拜,我要去另外一个世界了===");
}
}
class God implements Runnable{
@Override
public void run() {
int i=0;
while (true){
System.out.println("神圣在保佑我"+i++);
}
}
}
线程同步
并发:
同一个对象被多个线程同时操作
三大不安全的案例
不安全的买票
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/12 19:14
* @Version 1.0
*/
//有负数
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket=new BuyTicket();
new Thread(buyTicket,"苦逼的我").start();
new Thread(buyTicket,"牛逼的你们").start();
new Thread(buyTicket,"荒天帝").start();
}
}
class BuyTicket implements Runnable{
private int ticketNum=10;
boolean flag=true;
@Override
public void run() {
while (flag) {
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void buy() throws InterruptedException {
if (ticketNum<=0){
flag=false;
return;
}
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"买了第"+ticketNum--+"张票");
}
}
不安全的银行
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/12 20:29
* @Version 1.0
*/
public class UnsafeBank {
public static void main(String[] args) {
Account account = new Account(100,"结婚钱");
new Drawing(account,50,"你").start();
new Drawing(account,100,"你老婆").start();
}
}
//账户
class Account{
int money; //余额
String name; //卡名
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
//银行:模拟取款
class Drawing extends Thread{
Account account; //账户
//取了多少钱
int drawingMoney;
//现在手里有多少钱
int nowMoney;
public Drawing(Account account, int drawingMoney,String name) {
super(name);
this.account = account;
this.drawingMoney = drawingMoney;
}
@Override
public void run() {
//判断有没有钱
if (account.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money=account.money-drawingMoney; //卡内余额=余额-取的钱
nowMoney=drawingMoney+nowMoney; //手里的钱=取的钱+原来手里的钱
System.out.println(account.name+"当前的余额为:"+account.money);
// System.out.println(Thread.currentThread().getName()+"手里的钱:"+nowMoney);
System.out.println(this.getName()+"手里的钱:"+nowMoney);
}
}
不安全的集合
package TestLambda;
import java.util.ArrayList;
import java.util.List;
/**
* @Author 天红
* @Date 2021/6/12 21:05
* @Version 1.0
*/
public class UnsafeList {
public static void main(String[] args) throws InterruptedException {
List<String> list=new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
Thread.sleep(10);
System.out.println(list.size());
}
}
同步方法及同步块
安全的买票
一个对象直接在需要执行的方法上加上synchronized
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/12 19:14
* @Version 1.0
*/
public class SafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket=new BuyTicket();
new Thread(buyTicket,"苦逼的我").start();
new Thread(buyTicket,"牛逼的你们").start();
new Thread(buyTicket,"荒天帝").start();
}
}
class BuyTicket implements Runnable{
private int ticketNum=10;
boolean flag=true;
@Override
public void run() {
while (flag) {
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//synchronized锁的是this
public synchronized void buy() throws InterruptedException {
if (ticketNum<=0){
flag=false;
return;
}
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"买了第"+ticketNum--+"张票");
}
}
安全的银行
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/12 20:29
* @Version 1.0
*/
public class SafeBank {
public static void main(String[] args) {
Account account = new Account(1000,"结婚钱");
new Drawing(account,50,"你").start();
new Drawing(account,100,"你老婆").start();
}
}
//账户
class Account{
int money; //余额
String name; //卡名
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
//银行:模拟取款
class Drawing extends Thread{
Account account; //账户
int drawingMoney; //取了多少钱
int nowMoney; //现在手里有多少钱
public Drawing(Account account, int drawingMoney,String name) {
super(name);
this.account = account;
this.drawingMoney = drawingMoney;
}
@Override
public void run() {
//锁的对象就是变化的量,需要增删改的对象,锁共享的对象,唯一的对象
synchronized (account){
//判断有没有钱
if (account.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money=account.money-drawingMoney; //卡内余额=余额-取的钱
nowMoney=drawingMoney+nowMoney; //手里的钱=取的钱+原来手里的钱
System.out.println(account.name+"当前的余额为:"+account.money);
// System.out.println(Thread.currentThread().getName()+"手里的钱:"+nowMoney);
System.out.println(this.getName()+"手里的钱:"+nowMoney);
}
}
}
安全的集合
package TestLambda;
import java.util.ArrayList;
import java.util.List;
/**
* @Author 天红
* @Date 2021/6/12 21:05
* @Version 1.0
*/
public class SafeList {
public static void main(String[] args) throws InterruptedException {
List<String> list=new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
Thread.sleep(2000);
System.out.println(list.size());
}
}
JUC(CopyOnWriteArrayList)
package TestLambda;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @Author 天红
* @Date 2021/6/13 11:29
* @Version 1.0
*/
//测试JUC(就是并发包)安全类型的集合,安全的
public class TestJUC {
public static void main(String[] args) throws InterruptedException {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
Thread.sleep(2000); //为什么要睡眠,不睡还没add完,mian主线程一下就跑完了
System.out.println(list.size());
}
}
死锁
死锁的例子
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/13 14:46
* @Version 1.0
*/
public class DeadLock {
public static void main(String[] args) {
Makeup m1=new Makeup(0,"苏苏");
Makeup m2=new Makeup(1,"老婆");
m1.start();
m2.start();
}
}
//口红
class Lipstick{
}
//镜子
class Mirror{
}
class Makeup extends Thread{
// 需要的资源只有一份,用static来保证只有一份
static Lipstick lipstick=new Lipstick();
static Mirror mirror=new Mirror();
int choice; //选择
String girlName; //使用化妆品的人
public Makeup(int choice, String girlName) {
this.choice = choice;
this.girlName = girlName;
}
@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void makeup() throws InterruptedException {
if (choice==0){
synchronized (lipstick){
System.out.println(this.girlName+"获得了口红的锁");
Thread.sleep(1000);
synchronized (mirror){ //一秒钟后想获得镜子的锁
System.out.println(this.girlName+"获得镜子的锁");
}
}
}else{
synchronized (mirror){
System.out.println(this.girlName+"获得了镜子的锁");
Thread.sleep(2000);
synchronized (lipstick){ // 2秒钟后想获得口红的锁
System.out.println(this.girlName+"获得口红的锁");
}
}
}
}
}
死锁的解决
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/13 14:46
* @Version 1.0
*/
public class DeadLock {
public static void main(String[] args) {
Makeup m1=new Makeup(0,"苏苏");
Makeup m2=new Makeup(1,"老婆");
m1.start();
m2.start();
}
}
//口红
class Lipstick{
}
//镜子
class Mirror{
}
class Makeup extends Thread{
// 需要的资源只有一份,用static来保证只有一份
static Lipstick lipstick=new Lipstick();
static Mirror mirror=new Mirror();
int choice; //选择
String girlName; //使用化妆品的人
public Makeup(int choice, String girlName) {
this.choice = choice;
this.girlName = girlName;
}
@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void makeup() throws InterruptedException {
if (choice==0){
synchronized (lipstick){
System.out.println(this.girlName+"获得了口红的锁");
Thread.sleep(1000);
}
synchronized (mirror){ //一秒钟后想获得镜子的锁
System.out.println(this.girlName+"获得镜子的锁");
}
}else{
synchronized (mirror){
System.out.println(this.girlName+"获得了镜子的锁");
Thread.sleep(2000);
}
synchronized (lipstick){ // 2秒钟后想获得口红的锁
System.out.println(this.girlName+"获得口红的锁");
}
}
}
}
Lock锁
可重入锁 ReentrantLock()
package TestLambda;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Author 天红
* @Date 2021/6/13 17:13
* @Version 1.0
*/
public class TestLock {
public static void main(String[] args) {
TestLock02 testLock02 = new TestLock02();
new Thread(testLock02).start();
new Thread(testLock02).start();
new Thread(testLock02).start();
}
}
class TestLock02 implements Runnable{
int ticketNums=1000;
//定义lock锁i
private final ReentrantLock lock=new ReentrantLock();
@Override
public void run() {
while (true){
try{
lock.lock(); //加锁
if (ticketNums>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-->"+ticketNums--);
}
else {
break;
}
}finally {
lock.unlock(); //解锁
}
}
}
}
对比
线程协作(生产者消费者模式)
线程通信
解决方式
管程法
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/13 19:54
* @Version 1.0
*/
//测试:生产者消费者模型 ,利用缓冲区解决:管程法
//生产者,消费者,长跑,缓冲区
public class TestPC {
public static void main(String[] args) {
SynContainer c = new SynContainer();
new Producer(c).start();
new Consumer(c).start();
}
}
//生产者
class Producer extends Thread{
SynContainer container;
public Producer(SynContainer container) {
this.container = container;
}
//生产
@Override
public void run() {
for(int i=1;i<=100;i++)
{
container.push(new Chicken(i));
System.out.println("生产了第"+i+"只鸡");
}
}
}
//消费者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container) {
this.container = container;
}
//消费
@Override
public void run() {
for(int i=1;i<=100;i++)
{
System.out.println("消费了第"+container.pop().id+"只鸡");
}
}
}
//产品
class Chicken{
int id;//编号
public Chicken(int id)
{
this.id = id;
}
}
//缓冲区
class SynContainer{
//容器大小
Chicken[] chickens = new Chicken[10];
//容器计数器
int count = 0;
//生产者放入产品
public synchronized void push(Chicken chicken)
{
//如果容器满了,就需要等待消费者消费
if(count == chickens.length)
{
//通知消费者消费,生产等待
try {
this.wait();
}catch(Exception e) {
e.printStackTrace();
}
}
//如果没有满,我们就需要丢入产品
chickens[count] = chicken;
count++;
//可以通知消费者了
this.notifyAll();
}
//消费者消费产品
public synchronized Chicken pop() {
//判断能否消费
if(count==0)
{
//等待生产者生产,消费者等待
try {
this.wait();
}catch(Exception e)
{
e.printStackTrace();
}
}
//如果可以消费
count--;
Chicken chicken = chickens[count];
//吃完了,通知生产者生产
this.notifyAll();
return chicken;
}
}
#####
信号灯法
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/13 20:33
* @Version 1.0
*/
//测试生产消费者问题2,信号灯法,标志位解决
public class TestPC2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
TV tv = new TV();
new player(tv).start();
new Watcher(tv).start();
}
}
//生产者-》演员
class player extends Thread{
TV tv;
public player(TV tv)
{
this.tv = tv;
}
@Override
public void run() {
for(int i=0;i<20;i++)
{
if(i%2==0)
{
this.tv.play("完美世界");
}
else
{
this.tv.play("快来bibi看狂神");
}
}
}
}
//消费者-》观众
class Watcher extends Thread{
TV tv;
public Watcher(TV tv)
{
this.tv = tv;
}
@Override
public void run() {
for(int i=0;i<20;i++)
{
tv.watch();
}
}
}
//产品-》节目
class TV {
//演员录制,观众等待
//观众观看,演员等待
String voice;//表演的节目
boolean flag = true;
//录制
public synchronized void play(String voice) {
if(!flag)
{
try {
this.wait();
}catch(Exception e)
{
e.printStackTrace();
}
}
System.out.println("演员录制了"+voice);
//通知观众观看
this.notifyAll();
this.voice = voice;
this.flag = !this.flag;
}
//观众看
public synchronized void watch() {
if(flag)
{
try {
this.wait();
}catch(Exception e)
{
e.printStackTrace();
}
}
System.out.println("观看了"+voice);
//通知演员录制
this.notifyAll();
this.flag = !this.flag;
}
}
线程池
ExecutorService和Executors
package TestLambda;
/**
* @Author 天红
* @Date 2021/6/13 20:48
* @Version 1.0
*/
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//测试线程池
public class TestPool {
public static void main(String[] args) {
//1.创建线程池
ExecutorService service = Executors.newFixedThreadPool(10);
//执行
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
//关闭连接
service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
总结
package TestLambda;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
/**
* @Author 天红
* @Date 2021/6/13 20:59
* @Version 1.0
*/
//回顾总结线程的创建
public class ThreadNew {
public static void main(String[] args) {
new MyThread1().start();
new Thread(new MyThread2()).start();
FutureTask<Integer> f = new FutureTask<Integer>(new MyThread3());
new Thread(f).start();
try {
Integer i = f.get();
System.out.println(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//1.继承Thread类
class MyThread1 extends Thread {
@Override
public void run() {
System.out.println("MyThread1");
}
}
//2.实现Runnable接口
class MyThread2 implements Runnable {
@Override
public void run() {
System.out.println("MyThread2");
}
}
//3.实现Callable接口
class MyThread3 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("MyThread3");
return 100;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?