java地基--多线程

java地基--多线程,第1张

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

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

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

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

二、线程创建

  1. 继承Thread类

  2. 实现Runnable接口

1.Thread类方式创建线程
/**
 * @ClassName: TestThread
 * @Description:
 * @Author
 * @Date 2022/4/25
 * @Version 1.0
 */
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;

/**
 * @ClassName: TestRunnable
 * @Description:
 * @Author
 * @Date 2022/4/26
 * @Version 1.0
 */

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<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 com.kuang.demo1;



/**
 * @ClassName: StaticProxy
 * @Description: 静态代理
 * @Author
 * @Date 2022/4/26
 * @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("结婚之前,布置现场");
    }
}

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

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

  • 属于函数式编程概念

2.lamda表达式

避免内部类过多

代码更加简洁

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

理解函数式接口是关键

函数式接口定义:

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

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

package com.kuang.demo1;

/**
 * @ClassName: TestLamda
 * @Description:
 * @Author
 * @Date 2022/4/26
 * @Version 1.0
 */

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;


/**
 * @ClassName: SafeBuyTicket
 * @Description:
 * @Author
 * @Date 2022/4/26
 * @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 {
    // 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;


/**
 * @ClassName: SafeBank
 * @Description: 俩个线程 *** 作一个对象
 * @Author
 * @Date 2022/4/26
 * @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);
        }
    }

}

九、死锁

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

十、Lock锁

可重入锁

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


import java.util.concurrent.locks.ReentrantLock;

/**
 * @ClassName: ReentrantLock
 * @Description:
 * @Author
 * @Date 2022/4/26
 * @Version 1.0
 */
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:\Users\jiangshang\AppData\Roaming\Typora\typora-user-images\image-20220426173406146.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RZHgDIVO-1650966393407)(C:\Users\jiangshang\AppData\Roaming\Typora\typora-user-images\image-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());
         
     }
 }

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/738155.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存