多线程

p3继承thread类

  • 自定义线程类继承Thread类
  • 重写run()方法,编写线程执行体
  • 创建线程对象,调用start()方法启动线程
  • 注意run()和start()的区别
package com.kuang.demo01;


//创建线程方式一:继承Thread类,重写run()方法,调用start开启线程
//总结:注意线程开启不一定立即执行,由cpu调度执行
public class TestThread1  extends Thread{
    public void run(){//run方法线程体
        for(int i =0;i <20;i++){
            System.out.println("我在学习多线程--"+i);
        }
    }


    public static void main(String[] args) {
        //main线程,主线程

        //创建一个线程对象
        TestThread1 testThread1 = new TestThread1();

        //调用start()方法开启线程
        testThread1.start();

        for(int i =0;i <200;i++){
            System.out.println("我在学习多线程----------------"+i);
        }
    }

}

P4网图下载

应用:可以同时下载

p5实现runnable接口

  • 实现接口Runnable具有多线程nengl
  • 启动线程:传入目标对象+Thread对象.start()
  • 推荐使用,避免单继承局限,方便同一个对象被多个线程使用
package com.kuang.demo01;

public class TestThread3  implements Runnable{
    public void run(){
        //run方法线程体
        for(int i =0;i <200;i++){
            System.out.println("我在学习多线程--"+i);
        }
    }


    public static void main(String[] args) {
        //创建runnable接口的实现类对象
        TestThread3 testThread3 = new TestThread3();
        //创建线程对象通过线程对象来开启我们的线程,代理
        Thread thread = new Thread(testThread3);
        thread.start();
        for(int i =0;i <200;i++){
            System.out.println("我在学习多线程----------------"+i);
        }
    }

}

[图片上传失败...(image-a72b70-1616684383980)]

p6初识并发问题

package com.kuang.demo01;
//多个线程同时操作一个对象
//买火车票的例子
//发现问题:多个线程同时操作一个资源的情况,线程不安全,数据紊乱
public class TestThread4  implements Runnable{
    private  int ticketNums=10;
    @Override
    public void run() {
        while(true){
            if(ticketNums<=0)
            {
                break;
            }
            //模拟延时
            try{
                Thread.sleep(200);
            } catch (InterruptedException e){
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"票");
        }
    }

    public static void main(String[] args) {
        TestThread4 ticket = new TestThread4();
        new Thread(ticket,"小明").start();
        new Thread(ticket,"老师").start();
        new Thread(ticket,"黄牛").start();
    }
}

p7龟兔赛跑

package com.kuang.demo01;
//模拟龟兔赛跑
public class Race implements  Runnable {
    //胜利者
    private static String winner;
    @Override
    public void run() {
        for (int i = 1; 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();

    }
}


P8实现Callable接口(了解)

P9静态代理模式

package com.kuang.demo02;
//静态代理模式总结
//真是对象和代理对象都要实现同一个接口
//代理对象要代理真实角色.
//好处
    //代理对象可以做很多真实对象做不了的事情
    //真实对象专注做自己的事情
public class StaticProxy {
    public static void main(String[] args) {
        You you = new You();//你要结婚
        new Thread(()->System.out.println("我爱你")).start();
        new WeddingCompany(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("结婚之前,布置现场");
    }
}

p10Lamda表达式

  • 避免匿名内部类定义过多

函数式接口:任何接口如果只包含唯一一个抽象方法那么它就是一个函数式接口

对于函数式接口,我们可以通过lamda表达式俩创建该接口的对象

package com.kuang.lambda;
/*推导lambda表达式*/
public class TestLambda1 {
    //3.静态内部类
    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();
        //4.局部内部类
        class Like3 implements  ILike{
            @Override
            public void lambda() {
                System.out.println("I like lambda3");
            }
        }
        like = new Like3();
        like.lambda();
        //5.匿名内部类
        like = new ILike() {
            @Override
            public void lambda() {
                System.out.println("I like lambda4");
            }
        };
        like.lambda();
        //6.用 Lambda简化
        like = ()->{
            System.out.println("I like lambda5");
        };
        like.lambda();
    }
}
//1.定义一个函数式接口
interface ILike{
    void lambda();
}
//2.实现类
class Like implements  ILike{
    @Override
    public void lambda() {
        System.out.println("I like lambda");
    }
}

p11 线程停止

package com.kuang.state;

public class TestStop implements Runnable {
    //1.设置一个标志位
    private  boolean flag = true;
    @Override
    public void run() {
        int i=0;
        while (flag){
            System.out.println("run...Thread"+i++);
        }
    }
    //2.设置一个公开的方法停止线程,转换标志位
    public void  stop(){
        this.flag= false;
    }
    public static void main(String[] args) {
        TestStop testStop = new TestStop();
        new Thread(testStop).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("main"+i);
            if (i==900){
                //调用stop切换标志位,让线程停止
                testStop.stop();
                System.out.println("线程该停止了---------------");
            }
        }
    }
}

p12线程休眠

package com.kuang.state;

import java.text.SimpleDateFormat;
import java.util.Date;

//打印当前时间
public class TestSleep2{
     public static void main(String[] args) {
         //打印当前系统时间
         Date startTime = new Date(System.currentTimeMillis());//获取系统当前时间
        while(true){
            try{
                Thread.sleep(1000);
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
                startTime = new Date(System.currentTimeMillis());//更新当前时间
            } catch (InterruptedException e){
                e.printStackTrace();
            }
        }
     }

}

p13线程礼让_yield

package com.kuang.state;
//测试礼让线程
///礼让不一定成功,看CPU心情
public class TestYield {
    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()+"开始执行");
        if(Thread.currentThread().getName().equals("a")){
            System.out.println("a开始礼让");
            Thread.yield();
        }

        System.out.println(Thread.currentThread().getName()+"结束执行");
    }
}

p14线程轻质执行_join

join合并线程,待此线程执行完成后,在执行其他线程,其他线程阻塞

可以想象成插队

package com.kuang.state;
//测试join方法/想象为插队
public class TestJoin implements  Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            System.out.println("线程vip来了"+i);
        }
    }
    public static void main(String[] args) throws InterruptedException {
        //启动我们的线程
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);

        //主线程
        for (int i = 0; i < 25; i++) {
            if(i==20){
                thread.start();
                thread.join();//插队
            }
            System.out.println("main"+i);
        }
    }
}

p15观测线程状态

package com.kuang.state;
//观测测试线程状态
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);//new
        //观察启动后
        thread.start();//启动线程
        state = thread.getState();
        System.out.println(state);//Runnable
        while(state!=Thread.State.TERMINATED){//只要线程不终止就一直输出状态
            Thread.sleep(100);
            state  = thread.getState();//更新线程状态
            System.out.println(state);
        }
    }

}

p16线程的优先级

package com.kuang.state;
//测试线程的优先级
public class TestPriority {
    public static void main(String[] args) {
        //主线程默认优先级
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
        MyPriority myPriority = new MyPriority();
        Thread t1 = new Thread(myPriority);
        Thread t2 = new Thread(myPriority);
        Thread t3 = new Thread(myPriority);
        Thread t4 = new Thread(myPriority);
        Thread t5 = new Thread(myPriority);
        Thread t6 = new Thread(myPriority);
        //先设置优先级再启动
        t1.start();
        t2.setPriority(1);
        t2.start();
        t3.setPriority(4);
        t3.start();
        t4.setPriority(Thread.MAX_PRIORITY);
        t4.start();
        t5.setPriority(7);
        t5.start();
        t6.setPriority(8);
        t6.start();
    }
}
class  MyPriority implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
    }
}

p17守护线程

  • 线程分为用户线程守护线程
  • 虚拟机必须确保用户线程执行完毕
  • 虚拟机不用等待守护线程执行完毕
package com.kuang.state;
//测试守护线程
//上帝保护你
public class TestDaemon {

    public static void main(String[] args) {
        God god = new God();
        You you = new You();
        Thread thread  =new Thread(god);
        thread.setDaemon(true);//默认是false 表示是用户线程,正常的线程都是用户线程...
        thread.start();//上帝守护线程启动
        new Thread(you).start();//你 用户线程启动....
    }
}
//上帝
class   God implements Runnable{
    @Override
    public void run() {
        while(true){
            System.out.println("上帝保佑着你");
        }
    }
}
//你
class You implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 365000; i++) {
            System.out.println("你一生都开心的活着");
        }
        System.out.println("--------------goodbye world!------------");//hello world!
    }
}

p18线程同步机制

多个线程操作同一个资源

  • 并发:

    同一个对象多个线程同时操作

p19三大不安全案例

  • 买票,银行,线程不安全
package com.kuang.syn;

import java.util.ArrayList;
import java.util.List;

//线程不安全的集合
public class UnsafeList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                list.add(Thread.currentThread().getName());
            }).start();
        }
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }

}
package com.kuang.syn;
//不安全的取钱
//两个人去银行取钱,账户
public class UnsafeBank {
    public static void main(String[] args) {
        //账户
        Account account=new Account(100,"结婚基金");
        Drawing you = new Drawing(account,50,"小明");
        Drawing girlFriend = new Drawing(account,100,"girlFriend");
        you.start();
        girlFriend.start();
    }
}
//账户
class Account{
    int money;//余额
    String name;//卡名
    public Account(int money,String name){
        this.money= money;
        this.name=name;
    }
}
//bank 模拟取款
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 = nowMoney+ drawingMoney;
        System.out.println(account.name+"余额为"+account.money);
        System.out.println(this.getName()+"手里的钱"+nowMoney);
    }
}

p20 同步方法及同步块

同步块:cynchronized(obj){}

  • obj称之为同步监视器
    • obj可以是任何对象,但是推荐使用共享资源作为同步监视器
    • 同步方法无需指定同步监视器,因为同步方法中同步监视器就是this

p21死锁

产生死锁的四个必要条件

  • 互斥条件
  • 请求与保持 //一个进程因请求资源而阻塞时,对已获得的资源保持不放.
  • 不剥夺条件
  • 循环等待

p23lock锁

JDK5.0新增

class A{
    private final ReetrantLock lock = new TeenTrantLock();
    public void m(){
        lock.lock();
        try{
            //保证线程安全的代码;
        }
        finally{
            lock.unlock();
            //如果同步代码有异常,要将unlock()写入finally语句块 
        }
    }
}

P24生产者消费者问题

p25管程法

  • wait();线程一直等待直到其他线程通知与sleep不同会释放锁

  • notifyAll();唤醒同一个对象上所以调用wait()方法的线程,优先级别高的线程优先调度

package com.kuang.gaoji;
//测试:生产者消费者模型-->利用缓冲区解决:管程法
//生产者, 消费者, 产品, 缓冲区
public class TestPC {
    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++) {
            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 = 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;
    //生产者放入产品
    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;
    }
}

p26信号灯法

package com.kuang.gaoji;
//测试生产者消费者问题2:信号灯发,标志位解决
public class TestPC2 {
    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++) {
            tv.watch();
        }
    }
}
//产品->节目
class Tv {
    //演员表演,观众等待
    //观众观看,演员等待
    String voice;//表演的节目
    boolean flag = true;
    //表演
    public synchronized  void play(String voice){
        if(!flag){
            try {
                this.wait();
            } catch (InterruptedException 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 (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("观看了"+voice);
        //通知演员表演
        this.notifyAll();
        this.flag=!this.flag;
    }
}

p27线程池

一知半解以后再说

package com.kuang.gaoji;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestPool {
    public static void main(String[] args) {
        //1.创建服务,创建线程池
        //newFixedThreadPool 参数为:线程池大小
        ExecutorService service = Executors.newFixedThreadPool(10);
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        service.execute(new MyThread());
        //2.关闭链接
        service.shutdown();
    }
}
class MyThread implements Runnable{
    @Override
    public void run() {
            System.out.println(Thread.currentThread().getName());
    }
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一、Process与Thread 程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念 进程则是...
    知向谁边阅读 1,371评论 0 1
  • 线程简介 线程是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。多线程即多任务,比如边吃饭边...
    suger饭团阅读 2,206评论 0 1
  • 线程简介 任务、进程、线程、多线程 一个进程可以有多个线程,如视频中同时听声音、看视频、看弹幕等 Process与...
    小白菜aaa阅读 1,124评论 0 0
  • 1.线程,进程和多线程 1.程序:指指令和数据的有序集合,其本身没有任何意义,是一个静态的概念2.进程:指执行程序...
    前程有光阅读 2,682评论 0 0
  • 进程和线程 进程 所有运行中的任务通常对应一个进程,当一个程序进入内存运行时,即变成一个进程.进程是处于运行过程中...
    胜浩_ae28阅读 10,536评论 0 23