1、 继承Thread类 子类继承Thread类具备多线程能力 启动线程:子类对象.start() 不建议使用:避免OOP单继承局限性 2、 实现Runnable接口 推荐使用Runnable:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用(静态代理)。 一份资源,多个代理 例子-龟兔赛跑 优点: 理解Function Interface(函数式接口)是学习Java8 lamda表达式的关键坐在。 Lamda表达式的演化: lambda表达式简化: 例: 2、线程休眠 sleep 3、线程礼让 yield 4、线程合并 join 5、线程状态观测 State 5、线程优先级 Priority Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。 线程的优先级用数字表示,范围1~10 获取/改变优先级 优先级低只是意味着获得调度的概率低,并不是优先级低就不会被调用了,这都是看CPU的调度。 5、守护线程 daemon 多个线程操作同一个对象 1、线程同步 处理多线程问题时,多个线程访问同一个对象(并发问题),并且某个线程还想修改这个对象。这时候就需要线程同步,线程同步其实就是一种等待机制,多个需要同时访问此对象的进程进入这个对象的等待池形成队列,等待前面线程使用完毕,下一个线程再使用。 分析为什么会出现三个线程买同一张票的问题(重要!) JMM(Java Memory Model),是一种基于计算机内存模型,保证了Java程序在各种平台下对内存的访问都能保证效果一致的机制及规范。保证共享内存的原子性、可见性、有序性(这三个也是多线程的三大特性,划重点,面试经常问)。 可见性: 说了这么多,我们这时候应该知道之前写的模拟抢票demo为什么会有线程安全问题了把。就是因为各自都操作自己的工作内存,拿到主内存的值就开始操作。假设,这时候count为40,同一时间,来了三个线程,那这三个线程的工作内存拿到的值都是40,这样就会导致,这三个线程,都会抢到39这张票。 2、队列 和 锁 3、死锁 synchronized与Lock的对比 1、线程通信相关API 2、线程池
一、Java多线程常用的两种实现方法
new Thread(new ClassImplementRunnable()).start()
//一份资源 StartThread station = new StartThread(); //多个代理 new Thread(station,"user_a").start(); new Thread(station,"user_b").start(); new Thread(station,"user_c").start();
//模拟龟兔赛跑 public class Race implements Runnable { private static String winner; @Override public void run() { for (int i = 0; i <= 100; i++) { System.out.println(Thread.currentThread().getName() + "跑了" + i + "步"); //让兔子睡觉 if(Thread.currentThread().getName().equals("兔子") && i==40){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } if (getWinner(i)) { break; } } } //判断是否完成比赛 public boolean getWinner(int step) { //判断是否有胜利者 if (winner != null) { return true; } else { if (step >= 100) { winner = Thread.currentThread().getName(); System.out.println("winner is " + winner); return true; } else { return false; } } } public static void main(String[] args) { Race race = new Race(); new Thread(race,"乌龟").start(); new Thread(race,"兔子").start(); } }
二、静态代理
三、Lamda表达式
函数式接口定义:
public interface Runnable(){ public abstract void run(); }
//推导lamda表达式 public class TestLamda1 { //3.静态内部类 static class Like2 implements ILike{ @Override public void lamda() { System.out.println("i like lamda2"); } } public static void main(String[] args) { ILike like = new Like(); like.lamda(); like = new Like2(); like.lamda(); //4.局部内部类 class Like3 implements ILike{ @Override public void lamda() { System.out.println("i like lamda3"); } } like = new Like3(); like.lamda(); //5.匿名内部类,没有类的名称,必须借助接口或者父类 like = new ILike() { @Override public void lamda() { System.out.println("i like lamda4"); } }; like.lamda(); //6.用lamda简化 like = () -> { System.out.println("i like lamda5"); }; like.lamda(); } } //1.定义一个函数式接口 interface ILike{ void lamda(); } //2.实现类(常规用法) class Like implements ILike{ @Override public void lamda() { System.out.println("i like lamda"); } }
love = (int a, int b) -> { System.out.println("1"); System.out.println("2"); } //简化为 love = (a,b) -> { System.out.println("1"); System.out.println("2"); }
四、线程的状态
1、线程状态相关API
常用功能:
模拟网络延时、倒计时 //模拟倒计时 public static void tenDown(int num){ while (true){ System.out.println(num--); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if(num < 0){ break; } } }
//测试礼让 public class TestYield implements Runnable{ public static void main(String[] args) { TestYield testYield = new TestYield(); new Thread(testYield,"a").start(); new Thread(testYield,"b").start(); } @Override public void run() { System.out.println(Thread.currentThread().getName() + "开始执行..."); //礼让 Thread.yield(); System.out.println(Thread.currentThread().getName() + "结束执行。"); } }
//测试Join方法(可以想象为插队) public class JoinTest implements Runnable{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("线程vip来了:" + i); } } public static void main(String[] args) throws InterruptedException { //启动vip线程 //现在和main线程在同一个起跑线,当main线程到100时,礼让线程vip JoinTest joinTest = new JoinTest(); Thread thread = new Thread(joinTest); thread.start(); //main线程计数 for (int i = 0; i < 200; i++) { if(i==100){ thread.join();//插队 } System.out.println("main线程" + i); } } }
尚未启动的线程处于此状态。
在Java虚拟机中执行的线程处于此状态。
被阻塞的等待监视器锁定的线程处于此状态。
正在等待另一个线程执行特定动作的线程处于此状态。
正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
已退出的线程处于此状态。
Thread.MIN_PRIORITY = 1;
getPriority() / setPriority(int xxx)
五、线程同步
例子://不安全的买票 public class UnsafeBuyTicket { public static void main(String[] args) { BuyTicket buyTicket = new BuyTicket(); Thread th1 = new Thread(buyTicket,"小明"); Thread th2 = new Thread(buyTicket,"小红"); Thread th3 = new Thread(buyTicket,"小毛"); th1.start(); th2.start(); th3.start(); } } class BuyTicket implements Runnable{ private int ticketNums = 10;//票 boolean flag = true;//外部停止方式 @Override public void run() { //买票 while (flag){ try { buy(); } catch (InterruptedException e) { e.printStackTrace(); } } } public void buy() throws InterruptedException { //判断是否有票 if(ticketNums <= 0){ flag = false; return; } //模拟延时 Thread.sleep(1000); //买票 System.out.println(Thread.currentThread().getName() + "买到了第" + ticketNums-- + "张票"); } }
//安全的买票 public class UnsafeBuyTicket { public static void main(String[] args) { BuyTicket buyTicket = new BuyTicket(); Thread th1 = new Thread(buyTicket,"小明"); Thread th2 = new Thread(buyTicket,"小红"); Thread th3 = new Thread(buyTicket,"小毛"); th1.start(); th2.start(); th3.start(); } } class BuyTicket implements Runnable{ private int ticketNums = 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(ticketNums <= 0){ flag = false; return; } //模拟延时 Thread.sleep(100); //买票 System.out.println(Thread.currentThread().getName() + "买到了第" + ticketNums-- + "张票"); } }
//线程安全的集合 public class UnsafeList { public static void main(String[] args) { List<String> list = new ArrayList<String>(); for (int i = 0; i < 10000; i++) { new Thread(() -> { //synchronized同步块 synchronized (list) { list.add(Thread.currentThread().getName()); } }).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
多个线程各自占有一些共享的资源,并且互相等待其他线程占有的资源才能运行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情形。某一个同步代码块同时拥有“两个以上对象的锁”,就可能发生“死锁”问题。
4、Lock锁
Lock > 同步代码块(已经进入了方法体,分配了相应资源)> 同步方法(在方法体之外)六、线程协作
//1、测试生产者和消费者模型 --> 利用缓冲区解决:管程法 //生产者,消费者,产品,缓冲区 public class TestPC { public static void main(String[] args) { Container container = new Container(); Productor productor = new Productor(container); Consumer consumer = new Consumer(container); new Thread(productor).start(); new Thread(consumer).start(); } } //生产者 class Productor implements Runnable{ Container container = new Container(); public Productor(Container container) { this.container = container; } //生产 @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("生产了" + i + "只鸡"); container.push(new Chiecken(i)); } } } //消费者 class Consumer implements Runnable{ Container container = new Container(); public Consumer(Container container) { this.container = container; } //消费 @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("消费了-->" + container.pop().id + "只鸡"); } } } //产品 class Chiecken{ int id; public Chiecken(int id) { this.id = id; } } //缓冲区 class Container{ //需要一个容器存放产品 Chiecken[] chieckens = new Chiecken[10]; //容器计数器 int count = 0; //生产者放入产品 public synchronized void push(Chiecken chiecken){ //如果容器满了,就需要等待消费者消费 if(count == chieckens.length){ //通知消费者消费,生产等待 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果没满,我们就需要丢入产品 chieckens[count] = chiecken; count ++; //可以通知消费者消费了 this.notifyAll(); } //消费者消费产品 public synchronized Chiecken pop(){ if(count == 0){ //等待生产者生产,消费者等待 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果可以消费 count --; Chiecken chiecken = chieckens[count]; //吃完了,等待消费者生产 this.notifyAll(); return chiecken; } }
//2、解决生产者和消费者问题 信号灯法 public class TestPC2 { public static void main(String[] args) { Show show = new Show(); Player player = new Player(show); Watcher watcher = new Watcher(show); new Thread(player).start(); new Thread(watcher).start(); } } //演员 class Player implements Runnable{ Show show; public Player(Show show){ this.show = show; } @Override public void run() { for (int i = 0; i < 100; i++) { if(i%2 == 0){ this.show.play("钢铁侠"); }else { this.show.play("绿巨人"); } } } } //观众 class Watcher implements Runnable{ Show show; public Watcher(Show show) { this.show = show; } @Override public void run() { for (int i = 0; i < 100; i++) { this.show.watch(); } } } //产品————>表演 class Show { //演员表演,观众等待 T //观众观看,演员等待 F boolean flag = true; String voice; //表演 public synchronized void play(String voice) { if(!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("表演了" + voice); this.voice = voice; //通知观看 this.notifyAll(); flag = !flag; } //观看 public synchronized void watch(){ if(flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("观看了" + voice); //通知表演 this.notifyAll(); flag = !flag; } }
背景:经常创建和销毁、使用大量特别大的资源,比如并发情况下的线程,对性能影响很大,使用线程池便于线程管理。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算