多线程
1. 概述
- 程序是指令和数据的有序集合,是一个静态的概念
- 进程是执行程序的一次执行概念,是一个动态的概念
- 线程是CPU调度和执行的单位,一个进程至少有一个线程
2. Thread
2.1 创建线程
2.1.1 extends Thread
- 两条线程是并行交替执行
- 线程不一定立即执行
| package demo01; |
| |
| public class ThreadDemo01 extends Thread{ |
| @Override |
| public void run() { |
| |
| for (int i = 0; i < 20; i++) { |
| System.out.println("I am coding..."+i); |
| } |
| } |
| |
| public static void main(String[] args) { |
| |
| |
| ThreadDemo01 threadDemo01 = new ThreadDemo01(); |
| |
| threadDemo01.start(); |
| |
| |
| for (int i = 0; i < 20; i++) { |
| System.out.println("I am learn Thread..."+i); |
| } |
| } |
| } |
2.1.2 网图下载
| package demo01; |
| |
| import org.apache.commons.io.FileUtils; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.net.URL; |
| |
| |
| public class DownloderImage extends Thread{ |
| |
| private String url; |
| private String name; |
| |
| public DownloderImage(String url, String name) { |
| this.url = url; |
| this.name = name; |
| } |
| |
| @Override |
| public void run() { |
| WebDownloader webDownloader = new WebDownloader(); |
| webDownloader.downloader(url,name); |
| System.out.println("下载了文件名为:"+name+"的文件"); |
| } |
| |
| public static void main(String[] args) { |
| DownloderImage demo01 = new DownloderImage("https://images.cnblogs.com/cnblogs_com/blogs/783676/galleries/2335338/o_230812174934_bd.jpg","1.jpg"); |
| DownloderImage demo02 = new DownloderImage("https://images.cnblogs.com/cnblogs_com/blogs/783676/galleries/2335338/o_230812174934_bd.jpg","2.jpg"); |
| DownloderImage demo03 = new DownloderImage("https://images.cnblogs.com/cnblogs_com/blogs/783676/galleries/2335338/o_230812174934_bd.jpg","3.jpg"); |
| demo01.start(); |
| demo02.start(); |
| demo03.start(); |
| } |
| } |
| |
| class WebDownloader{ |
| |
| public void downloader(String url,String name){ |
| try { |
| |
| FileUtils.copyURLToFile(new URL(url),new File(name)); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| System.out.println("IO异常,downloader方法出现异常"); |
| } |
| } |
| } |
2.1.3 implements Runnable
| package demo01; |
| |
| public class ThreadDemo02 implements Runnable{ |
| @Override |
| public void run() { |
| |
| for (int i = 0; i < 20; i++) { |
| System.out.println("I am coding..."+i); |
| } |
| } |
| |
| public static void main(String[] args) { |
| |
| |
| ThreadDemo02 demo02 = new ThreadDemo02(); |
| |
| new Thread(demo02).start(); |
| |
| |
| for (int i = 0; i < 20; i++) { |
| System.out.println("I am learn Thread..."+i); |
| } |
| } |
| |
| } |
2.1.4 龟兔赛跑
| package demo01; |
| |
| |
| 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>=50 && i%10==0){ |
| try { |
| Thread.sleep(10); |
| } 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; |
| }else 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(); |
| } |
| } |
2.1.5 implements Callable
| package demo02; |
| |
| import org.apache.commons.io.FileUtils; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.net.URL; |
| import java.util.concurrent.*; |
| |
| |
| public class CallableDemo01 implements Callable { |
| |
| private String url; |
| private String name; |
| |
| public CallableDemo01(String url, String name) { |
| this.url = url; |
| this.name = name; |
| } |
| |
| @Override |
| public Boolean call() { |
| WebDownloader1 webDownloader = new WebDownloader1(); |
| webDownloader.downloader(url,name); |
| System.out.println("下载了文件名为:"+name+"的文件"); |
| return true; |
| } |
| |
| public static void main(String[] args) throws ExecutionException, InterruptedException { |
| CallableDemo01 demo01 = new CallableDemo01("https://images.cnblogs.com/cnblogs_com/blogs/783676/galleries/2335338/o_230812174934_bd.jpg","1.jpg"); |
| CallableDemo01 demo02 = new CallableDemo01("https://images.cnblogs.com/cnblogs_com/blogs/783676/galleries/2335338/o_230812174934_bd.jpg","2.jpg"); |
| CallableDemo01 demo03 = new CallableDemo01("https://images.cnblogs.com/cnblogs_com/blogs/783676/galleries/2335338/o_230812174934_bd.jpg","3.jpg"); |
| |
| ExecutorService es = Executors.newFixedThreadPool(3); |
| |
| Future<Boolean> result1 = es.submit(demo01); |
| Future<Boolean> result2 = es.submit(demo02); |
| Future<Boolean> result3 = es.submit(demo03); |
| |
| Boolean b1 = result1.get(); |
| Boolean b2 = result2.get(); |
| Boolean b3 = result3.get(); |
| |
| es.shutdown(); |
| } |
| } |
| |
| class WebDownloader1{ |
| |
| public void downloader(String url,String name){ |
| try { |
| |
| FileUtils.copyURLToFile(new URL(url),new File(name)); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| System.out.println("IO异常,downloader方法出现异常"); |
| } |
| } |
| } |
2.2 静态代理模式
| package demo03; |
| |
| public class ProxyDemo01 { |
| public static void main(String[] args) { |
| Wedding wedding = new Wedding(new You()); |
| |
| wedding.HappyMarry(); |
| } |
| } |
| |
| interface Marry{ |
| void HappyMarry(); |
| } |
| |
| class You implements Marry{ |
| |
| @Override |
| public void HappyMarry() { |
| System.out.println("马上要结婚了,开心"); |
| } |
| } |
| |
| class Wedding implements Marry{ |
| private Marry target; |
| |
| public Wedding(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("结婚之前,布置现场"); |
| } |
| } |
2.3 Lambda
- 简化代码
- 任何接口如果只包含唯一一个抽象方法,那么它就是一个函数式接口
| package demo03; |
| |
| public class LambdaDemo01 { |
| |
| static class Like2 implements ILike{ |
| @Override |
| public void lambda() { |
| System.out.println("I like lambda2"); |
| } |
| } |
| public static void main(String[] args) { |
| ILike like = new Like(); |
| like.lambda(); |
| like=new Like2(); |
| like.lambda(); |
| |
| |
| class Like3 implements ILike{ |
| @Override |
| public void lambda() { |
| System.out.println("I like lambda3"); |
| } |
| } |
| like = new Like3(); |
| like.lambda(); |
| |
| |
| like = new ILike() { |
| @Override |
| public void lambda() { |
| System.out.println("I like lambda4"); |
| } |
| }; |
| like.lambda(); |
| |
| |
| like = ()-> { |
| System.out.println("I like lambda5"); |
| }; |
| like.lambda(); |
| |
| } |
| } |
| |
| interface ILike{ |
| void lambda(); |
| } |
| |
| class Like implements ILike{ |
| @Override |
| public void lambda() { |
| System.out.println("I like lambda"); |
| } |
| } |
| package demo03; |
| |
| public class LambdaDemo02 { |
| public static void main(String[] args) { |
| ILove love = new Love(); |
| love.love("quinn"); |
| love = new ILove() { |
| @Override |
| public void love(String name) { |
| System.out.println(name+" love java"); |
| } |
| }; |
| love.love("morita"); |
| |
| |
| love = (String name)-> { |
| System.out.println(name+" love java"); |
| }; |
| love.love("Cx330"); |
| |
| love = (name)->{ |
| System.out.println(name+" love java"); |
| }; |
| love.love("yq"); |
| |
| love = name -> System.out.println(name+" love java"); |
| love.love("zy"); |
| |
| } |
| } |
| interface ILove{ |
| void love(String name); |
| } |
| class Love implements ILove{ |
| |
| @Override |
| public void love(String name) { |
| System.out.println(name+" love java"); |
| } |
| } |
2.4 线程五大状态
- 创建状态
- 就绪状态
- 阻塞状态
- 运行状态
- 死亡状态
| package demo05; |
| |
| public class StatusDemo01 { |
| |
| 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); |
| |
| thread.start(); |
| state = thread.getState(); |
| System.out.println(state); |
| |
| while (state != Thread.State.TERMINATED){ |
| Thread.sleep(100); |
| state = thread.getState(); |
| System.out.println(state); |
| } |
| } |
| } |
2.5 线程停止
| package demo04; |
| |
| |
| public class StopDemo01 implements Runnable{ |
| |
| private boolean flag = true; |
| @Override |
| public void run() { |
| int i = 0; |
| while (flag){ |
| System.out.println("run.....Thread"+(i++)); |
| } |
| } |
| |
| public void stop(){ |
| this.flag = false; |
| } |
| |
| public static void main(String[] args) { |
| StopDemo01 demo01 = new StopDemo01(); |
| new Thread(demo01).start(); |
| for (int i = 0;i < 1000;i++){ |
| System.out.println("main"+i); |
| if (i == 500){ |
| demo01.stop(); |
| System.out.println("线程停止"); |
| } |
| } |
| } |
| } |
2.6 模拟延时
| package demo04; |
| |
| public class SleepDemo01 implements Runnable{ |
| private int ticketNums = 10; |
| |
| @Override |
| public void run() { |
| while (true){ |
| if (ticketNums <= 0){ |
| break; |
| } |
| try { |
| Thread.sleep(100); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| System.out.println(Thread.currentThread().getName()+"--->拿到了第"+(ticketNums--)+"票"); |
| } |
| } |
| |
| public static void main(String[] args) { |
| SleepDemo01 demo01 = new SleepDemo01(); |
| new Thread(demo01,"小明").start(); |
| new Thread(demo01,"小红").start(); |
| new Thread(demo01,"小黄").start(); |
| } |
| |
| } |
| package demo04; |
| |
| import java.text.SimpleDateFormat; |
| import java.util.Date; |
| import java.util.concurrent.BrokenBarrierException; |
| |
| |
| public class SleepDemo02{ |
| |
| public static void timeDown() throws Exception { |
| int num = 10; |
| while (true){ |
| Thread.sleep(1000); |
| System.out.println(num--); |
| if (num <= 0){ |
| break; |
| } |
| |
| } |
| } |
| |
| public static void main(String[] args) { |
| |
| |
| |
| |
| |
| |
| Date date = new Date(System.currentTimeMillis()); |
| 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(); |
| } |
| } |
| } |
| } |
2.7 Yield:线程礼让
- 让当前正在执行的线程停止,但不阻塞
- 礼让不一定成功
| package demo04; |
| |
| public class YieldDemo01 { |
| public static void main(String[] args) { |
| MyYield myYield = new MyYield(); |
| new Thread(myYield,"a").start(); |
| new Thread(myYield,"b").start(); |
| } |
| } |
| |
| class MyYield implements Runnable{ |
| |
| @Override |
| public void run() { |
| System.out.println(Thread.currentThread().getName()+"....start...."); |
| Thread.yield(); |
| System.out.println(Thread.currentThread().getName()+"....stop....."); |
| } |
| } |
2.8 Join:线程强制执行
| package demo04; |
| |
| public class JoinDemo01 implements Runnable{ |
| @Override |
| public void run() { |
| for (int i = 0; i < 300; i++) { |
| System.out.println("线程vip来了"+i); |
| } |
| } |
| |
| public static void main(String[] args) throws Exception { |
| JoinDemo01 demo01 = new JoinDemo01(); |
| Thread thread = new Thread(demo01); |
| thread.start(); |
| |
| for (int i = 0; i < 500; i++) { |
| if (i == 100){ |
| thread.join(); |
| } |
| System.out.println("main:"+i); |
| } |
| } |
| } |
2.9 线程优先级
| package demo05; |
| |
| |
| |
| public class PriorityDemo01 { |
| public static void main(String[] args) { |
| |
| System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); |
| |
| MyPriority priority = new MyPriority(); |
| Thread thread1 = new Thread(priority); |
| Thread thread2 = new Thread(priority); |
| Thread thread3 = new Thread(priority); |
| Thread thread4 = new Thread(priority); |
| |
| thread1.start(); |
| |
| thread2.setPriority(1); |
| thread2.start(); |
| |
| thread3.setPriority(4); |
| thread3.start(); |
| |
| thread4.setPriority(Thread.MAX_PRIORITY); |
| thread4.start(); |
| |
| } |
| } |
| class MyPriority implements Runnable{ |
| |
| @Override |
| public void run() { |
| System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); |
| } |
| } |
2.10 守护线程
- 线程分为用户线程和守护线程
| package demo05; |
| |
| public class DaemonDemo01 { |
| public static void main(String[] args) { |
| God god = new God(); |
| You you = new You(); |
| |
| Thread t1 = new Thread(god); |
| t1.setDaemon(true); |
| t1.start(); |
| |
| new Thread(you).start(); |
| |
| } |
| } |
| |
| class You implements Runnable{ |
| @Override |
| public void run() { |
| for (int i = 0; i < 36500; i++) { |
| System.out.println("你一生都开心的活着"); |
| } |
| System.out.println("=======goodbye!=========="); |
| } |
| } |
| class God implements Runnable{ |
| @Override |
| public void run() { |
| while (true){ |
| System.out.println("上帝保护你"); |
| } |
| } |
| } |
3. 线程同步
- 多线程操作同一个资源
4. 死锁
4.1 产生条件
- 互斥条件:一个资源每次只能被一个进程使用
- 请求与保持条件:一个进程因请求资源而阻塞时,对方已获得的资源保持不放
- 不剥夺条件:进程已获得的资源在未使用完之前不能强行剥夺
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
| package demo07; |
| |
| public class DeadLockDemo01 { |
| public static void main(String[] args) { |
| Makeup m1 = new Makeup(0,"lisa"); |
| Makeup m2 = new Makeup(1,"lily"); |
| |
| m1.start(); |
| m2.start(); |
| } |
| } |
| |
| class Lipstick{ |
| |
| } |
| class Mirror{ |
| |
| } |
| class Makeup extends Thread{ |
| |
| static Lipstick lip = new Lipstick(); |
| static Mirror mi = 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 (lip){ |
| System.out.println(this.girlName+"获得口红的锁"); |
| sleep(1000); |
| synchronized (mi){ |
| System.out.println(this.girlName+"获得镜子的锁"); |
| } |
| } |
| }else { |
| synchronized (mi){ |
| System.out.println(this.girlName+"获得镜子的锁"); |
| sleep(2000); |
| } |
| synchronized (lip){ |
| System.out.println(this.girlName+"获得口红的锁"); |
| } |
| } |
| } |
| } |
5. 锁
| package demo07; |
| |
| import java.util.concurrent.locks.ReentrantLock; |
| |
| public class LockDemo01 { |
| public static void main(String[] args) { |
| TestClock testClock = new TestClock(); |
| new Thread(testClock).start(); |
| new Thread(testClock).start(); |
| new Thread(testClock).start(); |
| } |
| } |
| class TestClock implements Runnable{ |
| int tickNums = 10; |
| private ReentrantLock lock = new ReentrantLock(); |
| |
| @Override |
| public void run() { |
| while (true){ |
| try { |
| |
| lock.lock(); |
| if (tickNums > 0) { |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| System.out.println(tickNums--); |
| } else { |
| break; |
| } |
| }finally { |
| |
| lock.unlock(); |
| } |
| |
| } |
| } |
| } |
6. 生产者消费者问题
6.1 管程法
| package demo08; |
| |
| |
| public class PCDemo01 { |
| public static void main(String[] args) { |
| SynContainer container = new SynContainer(); |
| new Productor(container).start(); |
| new Consumer(container).start(); |
| } |
| } |
| |
| class Productor extends Thread{ |
| SynContainer container; |
| public Productor(SynContainer container) { |
| this.container = container; |
| } |
| |
| @Override |
| public void run() { |
| for (int i = 0; i < 100; i++) { |
| System.out.println("生产了"+i+"只鸡"); |
| container.push(new Chicken(i)); |
| } |
| } |
| } |
| |
| class Consumer extends Thread{ |
| SynContainer container; |
| public Consumer(SynContainer container) { |
| this.container = container; |
| } |
| |
| @Override |
| public void run() { |
| for (int i = 0; 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 (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| |
| } |
| |
| |
| chickens[count] = chicken; |
| count++; |
| |
| this.notifyAll(); |
| } |
| |
| |
| public synchronized Chicken pop(){ |
| |
| if (count == 0){ |
| |
| try { |
| this.wait(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| count--; |
| Chicken chicken = chickens[count]; |
| this.notifyAll(); |
| |
| |
| return chicken; |
| |
| } |
| } |
6.2 信号灯法
| package demo08; |
| |
| import org.omg.CORBA.TCKind; |
| |
| |
| public class PCDemo02 { |
| public static void main(String[] args) { |
| 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("广告播放中"); |
| } |
| } |
| } |
| } |
| |
| |
| class Watcher extends Thread{ |
| TV tv; |
| public Watcher(TV tv) { |
| this.tv = tv; |
| } |
| @Override |
| public void run() { |
| for (int i = 0; i < 20; i++) { |
| this.tv.watch(); |
| } |
| } |
| } |
| |
| |
| class TV { |
| |
| String voice; |
| boolean flag = true; |
| |
| public synchronized void play(String voice){ |
| if (flag == false){ |
| try { |
| this.wait(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| System.out.println("演员表演了:"+voice); |
| this.voice = voice; |
| this.notifyAll(); |
| this.flag = !this.flag; |
| } |
| |
| |
| public synchronized void watch(){ |
| if (flag){ |
| try { |
| this.wait(); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| } |
| System.out.println("观众观看了:"+voice); |
| this.notifyAll(); |
| this.flag = !this.flag; |
| } |
| |
| } |
7. 线程池
| package demo09; |
| |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.Executors; |
| |
| public class PoolDemo01 { |
| public static void main(String[] args) { |
| ExecutorService pool = Executors.newFixedThreadPool(10); |
| |
| pool.execute(new MyThread()); |
| pool.execute(new MyThread()); |
| pool.execute(new MyThread()); |
| pool.execute(new MyThread()); |
| pool.execute(new MyThread()); |
| |
| pool.shutdown(); |
| } |
| } |
| class MyThread implements Runnable{ |
| @Override |
| public void run() { |
| System.out.println(Thread.currentThread().getName()); |
| } |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步