栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java地基--多线程

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java地基--多线程

多线程 一、程序,进程,线程

程序: 是指令和数据的有序集合, 本身没任何的含义,是一个静态概念

进程: 是执行程序的一次执行过程 一个动态概念

线程 : 一个进程可以有多个线程,当然至少有一个线程,否则无意义,线程是CPU执行和调度的单位

二、线程创建

  1. 继承Thread类

  2. 实现Runnable接口

1.Thread类方式创建线程
public class TestThread extends  Thread{

    @Override
    public void run() {
        for (int i  = 0; i<200; i++) {
            System.out.println(currentThread().getName() + "我在看代码------------------" + i );
        }
    }

    public static  void  main(String[] args) {
        TestThread testThread = new TestThread();
        testThread.start();

        for (int i = 0; i < 100; i++) {
            System.out.println(currentThread().getName()+"在学习多线程---" + i);
        }
    }
}
2.实现Runnable接口创建线程
package com.kuang.demo1;



public class TestRunnable implements  Runnable {

    @Override
    public void run() {
        for (int i  = 0; i<200; i++) {
            System.out.println( "我在看代码------------------" + i );
        }
    }

    public static  void  main(String[] args) {
        TestRunnable testRunnable = new TestRunnable();
        new Thread(testRunnable).start();

        for (int i = 0; i < 100; i++) {
//            try {
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
            System.out.println("在学习多线程---" + i);
        }
    }
}

3.总结
  • 继承Thread类

    • 子类继承Thread类具备多线程能力
    • 启动线程 子类对象.start()
  • 实现Runnable接口 推荐使用

    • 实现Runnable具备多线程能力

    • 启动线程: 传入目标对象+ Thread对象.start()

tip:还有一种创建线程方式 了解即可

public class TestCallable implements Callable {
     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=https://www.mshxw.com/skin/sinaskin/image/nopic.gif", "1.jpg");
         TestCallable t2 = new TestCallable("https://gimg2.baidu.com/image_search/src=https://www.mshxw.com/skin/sinaskin/image/nopic.gif", "2.jpg");
         TestCallable t3 = new TestCallable("https://gimg2.baidu.com/image_search/src=https://www.mshxw.com/skin/sinaskin/image/nopic.gif", "3.jpg");
 ​
 ​
 ​
 //        创建执行服务
         ExecutorService service = Executors.newFixedThreadPool(3);
 ​
 //        提交执行
         Future r1 = service.submit(t1);
         Future r2 = service.submit(t2);
         Future 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 com.kuang.demo1;





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("结婚之前,布置现场");
    }
}

四、lamda表达式 1.含义
  • 希腊字母第十一位字母

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

  • 属于函数式编程概念

2.lamda表达式

避免内部类过多

代码更加简洁

只留核心代码 去掉无意义代码

理解函数式接口是关键

函数式接口定义:

  1. 任何接口都只有一个抽象方法,那么他就是一个函数式接口

  2. 函数接口可以用lamda简化

package com.kuang.demo1;



public class TestLamda {
    public static void main(String[] args) {
//        //1.普通方式
//        Like like = new Like();
//        like.Lambda();

//        //2.局部类部类
//        class  Like3 implements ILike {
//            @Override
//            public void Lambda() {
//                System.out.println("I like yan3");
//            }
//        }
//        ILike like=new Like3();
//        like.Lambda();
//    }
//        //3.匿名内部类
//        ILike like = null;
//        like = new ILike() {
//            @Override
//            public void Lambda() {
//                System.out.println("I like yan4");
//            }
//        };
//        like.Lambda();
        //4.用lambda简化
        ILike like = null;
        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");
    }
}

五、线程状态


1.停止线程

2.休眠线程

3.线程礼让

4.join合并线程

5.线程状态观测(五个)
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);     //输出状态
        }


    }
}
六、线程的优先级

七、守护线程

概念

代码测试:

package com.kuang.demo1;

public class TestDaemon {
    public static void main(String[] args) {
        Ysou you = new Ysou();
        God god = new God();

        Thread thread = new Thread(god);
        thread.setDaemon(true); //默认flase  表示守护线程
        thread.start();     //上帝,守护线程启动

        new Thread(you).start();    //你   用户线程启动

    }
}


class Ysou 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++);
        }
    }
}

八、线程同步 1.概念:

2.方式
  • 同步方法

  • 同步代码块

synchronized同步方法

package com.kuang.demo1;



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 {
    // 10张票
    private int ticketNum = 10;
    // 标注
    boolean flag = true;
    @Override
    public void run() {
        while(flag) {
            try{
                buy();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public synchronized  void buy() throws InterruptedException {
        if (ticketNum <= 0) {
            flag = false;
            return;
        }
        Thread.sleep(100);
        System.out.println(Thread.currentThread().getName()+"买了第"+ticketNum--+"张票");
    }
}

synchronized 代码块方法

package com.kuang.demo1;



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);
        }
    }

}

九、死锁

1.死锁的条件以及解决办法

十、Lock锁

可重入锁

可重入锁 ReentrantLock()
package com.kuang.demo1;


import java.util.concurrent.locks.ReentrantLock;


public class TestReentrantLock {
    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;
    //定义ReentrantLock
    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();  //解锁
            }
        }
    }
}

Lock锁和syncronized对比

对比

十一、线程协作 线程通信

线程通信分析

解决办法

  1. 管程法---- 利用缓冲区

//测试:生产者消费者模型 ,利用缓冲区解决:管程法
//生产者,消费者,长跑,缓冲区
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;
    }
}
  1. 信号灯法----利用标志位

//测试生产消费者问题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;
     }
 }
十二、线程池

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AWnovN3S-1650966393406)(C:UsersjiangshangAppDataRoamingTyporatypora-user-imagesimage-20220426173406146.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RZHgDIVO-1650966393407)(C:UsersjiangshangAppDataRoamingTyporatypora-user-imagesimage-20220426173430054.png)]

ExecutorService和Executors
package TestLambda;

 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());
         
     }
 }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/837839.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号