java多线程学习 代码笔记

继承Thead创建线程

public class Threadtest extends Thread{

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("A" + i);
        }
    }
    public static void main(String[] args) {
        Threadtest threadtest = new Threadtest();
        threadtest.run();
        for (int i = 0; i < 500; i++) {
            System.out.println("B" + i);
        }

    }
}

继承Runable 创建线程

public class Threadtest2 implements Runnable{
        //多个线程同时操作一个对象
    private static int ticketNums = 10;
    @Override
    public void run() {
           if(Thread.currentThread().getName().equals("A")){
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
           while (true) {
               if (ticketNums < 0) break;
               try {
                   Thread.sleep(200);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               System.out.println(Thread.currentThread().getName() + "拿到了第" + ticketNums + "票");
               ticketNums--;
           }

    }
    public static void main(String[] args) {
        Threadtest2 test = new Threadtest2();
        new Thread(test,"A").start();
        new Thread(test,"B").start();//使用了静态代理 代理了这个类的线程
        new Thread(test,"C").start();
    }
}

lamda表达式的演变过程



// 推到lamda表达式
// 函数式接口 就是一个接口只有一个方法的那种
public class Lamda {
    //静态内部类
    static   class Like2 implements Like{

        @Override
        public void lamda() {
            System.out.println("Like");
        }
    }
    public static void main(String[] args) {
        Like like = new Like1();
        like.lamda();
        Like like1 = new Like2();
        like1.lamda();
        // 4.局部内部类
        class Like3 implements Like{

            @Override
            public void lamda() {
                System.out.println("Like");
            }
        }
        Like like2 = new Like3();
        like2.lamda();
        // 5.局部内部类
        like = new Like() {
            @Override
            public void lamda() {
                System.out.println("leike1");
            }
        };
        like.lamda();
        //6. 用lamba简化
        Like like6 = ()->{
            System.out.println("like222");
        };
        like6.lamda();
    }

}
// 1.定义一个函数式接口
interface  Like{
    void lamda();
}

//2.实现类
class Like1 implements Like{

    @Override
    public void lamda() {
        System.out.println("Like");
    }
}

线程的5种状态

在这里插入图片描述

线程方法 在这里插入图片描述

停止线程 在这里插入图片描述

标志位停止线程的代码
public class stop implements Runnable{
    private boolean flag = true;
    @Override
    public void run() {
        int i = 0 ;
        while(flag){
            System.out.println(":"+i++);
        }
    }

    public void stop(){
        flag = false;
    }

    public static void main(String[] args) throws InterruptedException {
        stop stop = new stop();
        new Thread(stop).start();
        Thread.sleep(20);
        stop.stop();
    }
}

线程休眠

在这里插入图片描述

public class Threadtest2 implements Runnable{
        //多个线程同时操作一个对象
    // 模拟网络延时,放大进程间的问题
    private static int ticketNums = 10;
    @Override
    public void run() {
           if(Thread.currentThread().getName().equals("A")){
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
           while (true) {
               if (ticketNums < 0) break;
               try {
                   Thread.sleep(200);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               System.out.println(Thread.currentThread().getName() + "拿到了第" + ticketNums + "票");
               ticketNums--;
           }

    }
    public static void main(String[] args) {
        Threadtest2 test = new Threadtest2();
        new Thread(test,"A").start();
        new Thread(test,"B").start();
        new Thread(test,"C").start();
    }
}

利用线程休眠看系统时间

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

public class Threadtest1 {

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

线程礼让 yield

在这里插入图片描述

public class testyield  {
    // 礼让不一定成功 看cup心情


    public static void main(String[] args) {
//        MYyeild mYyeild = new MYyeild();
//        new Thread(mYyeild,"a").start();
//        new Thread(mYyeild,"b").start();
        new Thread(()->{ //lamda表达式
            System.out.println("start1");
            Thread.yield();
            System.out.println("end1");
        }).start();
        new Thread(()->{
            System.out.println("start2");
//            Thread.yield();
            System.out.println("end2");
        }).start();

    }
}
//class MYyeild implements Runnable{
//    @Override
//    public void run() {
//        System.out.println("start");
//        Thread.yield();
//        System.out.println("end");
//    }
//}

join

  • join 合并线程 ,等这个线程执行完成后,在执行其他线程,其他线程阻塞
  • 可以理解为插队
public class join implements Runnable{
   @Override
   public void run() {
       for (int i = 0; i < 100; i++) {
           System.out.println(i);
       }
   }
   public static void main(String[] args) throws InterruptedException {
       join join = new join();
       Thread thread = new Thread(join);
       for (int i = 0; i < 500; i++) {
           if(i==20){
               thread.start();
               thread.join();
           }
           System.out.println("main"+i);
       }
   }
}

线程状态观测

在这里插入图片描述

观测线程状态
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);
        thread.start();
        state = thread.getState();
        System.out.println(state);//Run

        while(state != Thread.State.TERMINATED){//只要线程不终止,就一直输出状态
            Thread.sleep(100);
            state = thread.getState();//更新线程状态
            System.out.println(state);//输出状态
        }
        thread.start();//(会报错)线程死亡后就不能再次启动了
    }
}
线程的优先级
代码
public class TestPriority{

    public static void main(String[] args) {
        System.out.println("main"+Thread.currentThread().getPriority());
        Mypriorty mypriorty = new Mypriorty();
        Thread t1 = new Thread(mypriorty);
        Thread t2 = new Thread(mypriorty);
        Thread t3 = new Thread(mypriorty);
        Thread t4 = new Thread(mypriorty);
        t1.start();


        t2.setPriority(1);
        t2.start();


        t3.setPriority(4);
        t3.start();

        t4.setPriority(Thread.MAX_PRIORITY);//并不是设置的优先级高的就会先启动
        t4.start();
        
    }
}
class Mypriorty implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"->"+Thread.currentThread().getPriority());
    }
}

线程的分类

  • 守护线程(gc垃圾回收)
  • 用户线程(main方法)
  • 虚拟机必须确保用户线程执行完毕
  • 虚拟机不用等待守护线程执行完毕(就是用户线程结束 虚拟机就会停止)
public class Testdaemon {

  public static void main(String[] args) {
      God god = new God();
      he he = new he();
      Thread thread = new Thread(god);
      thread.setDaemon(true);// 默认值式false 表示用户线程,正常的线程都是用户线程
      thread.start();// 上帝守护的线
      new Thread(he).start();
  }
}
class God implements Runnable{

  @Override
  public void run() {
      while (true){
          System.out.println("上帝");
      }
  }
}

class he implements Runnable{
      @Override
      public void run() {
          for (int i = 0; i < 36500; i++) {
              System.out.println("活着");
          }
          System.out.println("走了");
      }
  }
}

线程同步

  • 线程不安全的例子
public class UnsafeuyTicket {

    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{

    private  int ticketnums = 10;
    boolean flag = true;//外部停止方式
    @Override
    public void run() {
        while (flag){
            try {
                Thread.sleep(100);
                buy();
                ticketnums--;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
    private void buy(){
        if(ticketnums<=0) {
            flag = false;
            return  ;
        }
        System.out.println(Thread.currentThread().getName()+"拿到"+ticketnums);
    }

}

  • Arrylist线程不安全的例子
import java.util.ArrayList;
import java.util.List;

public class UnsafeList {
  public static void main(String[] args) throws InterruptedException {
      List<String> list = new ArrayList<>();
      for (int i = 0; i < 10000; i++) {
          new Thread(()->{
              list.add(Thread.currentThread().getName());//出现问题时 两个线程同时存储一个下标的值就会List就会被修改.
          }).start();
      }
      Thread.sleep(1000);
      System.out.println(list.size());
  }

}

同步方法和同代码块

  • sychronized方法
public class UnsafeuyTicket {

    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{

    private  int ticketnums = 10;
    boolean flag = true;//外部停止方式
    @Override
    public void run() {
        while (flag){
            try {
                Thread.sleep(100);
                buy();
                ticketnums--;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
    private synchronized void buy(){
        if(ticketnums<=0) {
            flag = false;
            return  ;
        }
        System.out.println(Thread.currentThread().getName()+"拿到"+ticketnums);
    }

}

  • 解决arrylist线程不安全的例子
import java.util.ArrayList;
import java.util.List;

public class UnsafeList {
   public static void main(String[] args) throws InterruptedException {
       List<String> list = new ArrayList<>();
       for (int i = 0; i < 10000; i++) {
           new Thread(()->{
               synchronized (list){ //同步代码块  锁的是发生变化的对象
                   list.add(Thread.currentThread().getName());//出现问题时 两个线程同时存储一个下标的值就会List就会被修改.
               }

           }).start();
       }
       Thread.sleep(1000);
       System.out.println(list.size());
   }

}

死锁产生的必要条件

  • 互斥:每个资源只能被一个进程使用
  • 占有和等待:已经得到了资源的进程可以再申请新的资源并且不释放以获得的资源
  • 不可抢占:已经分配给一个进程的资源不能被抢占,只能被显示的释放
  • 环路等待:两个或以上的进程组成一条环路,每个进程都在等待下一个进程占有的资源
  • 有一条不满足就不会发生死锁

死锁产生代码案例

package lock;
//死锁,两个或以上线程占用对方需要的资源,互不释放 形成思索
public class Deadlock {
    public static void main(String[] args) {
        new Thread(new boy(0,"小明"),"a").start();
        new Thread(new boy(1,"小红"),"b").start();
    }
}
class apple{

}
class banana{

}
class boy implements Runnable{

    private static apple apple = new apple();
    private static banana banana = new banana();
    private int choice;
    private String name;
    public boy(int choice,String name){
        this.choice = choice;
        this.name = name;
    }
    @Override
    public void run() {
        try {
            makeup();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    private void  makeup() throws InterruptedException {
        if(choice==0){
            synchronized (apple){//锁住苹果这个资源 再去拿香蕉
                System.out.println(this.name+"拿到了苹果");
                Thread.sleep(2000);//添加睡眠是怕同时拿到了 两把锁 影响实践的结果
                synchronized (banana){ //将这个锁拿到外面就可以解决  让他让出苹果 在去拿香蕉 就不会影响别人拿苹果
                    System.out.println(this.name+"拿到香蕉");
                }
            }
        }else{
            synchronized (banana) {//锁住香蕉这个资源 再去拿苹果
                System.out.println(this.name + "拿到了香蕉");
                Thread.sleep(2000);//添加睡眠是怕同时拿到了 两把锁 影响实践的结果
                synchronized (apple) {
                    System.out.println(this.name + "拿到苹果");
                }
            }
        }
    }
}

将同步块移出就可以得到 解决争夺资源,却不释放资源

在这里插入图片描述

lock与synchronized 的对比在这里插入图片描述

lock代码案例
package lock;

import java.util.concurrent.locks.ReentrantLock;

public class Testlock {

    public static void main(String[] args) {
        Testlock2 testlock2 = new Testlock2();
        new Thread(testlock2,"a").start();

        new Thread(testlock2,"b").start();
        new Thread(testlock2,"c").start();

    }
}

class Testlock2 implements Runnable{

    private  static int ticketmuns = 10;

    private  final ReentrantLock lock = new ReentrantLock();//可重入锁


    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        while(true){
            try{
                lock.lock();//加锁
                if(ticketmuns > 0){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" :"+ticketmuns--);
                }else{
                    break;
                }
            }finally {
                lock.unlock();//解锁
            }

        }
    }
}

线程协作 通信

  • 生产者消费者(管程法)
package lock;

//测试,生产者消费者模型 --> 利用缓冲区解决 管程法
// 生产者,消费者,产品,缓冲区

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++) {
           try {
               container.push(new Chicken(i));
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
           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++) {
           Chicken chicken = container.pop();
           System.out.println("消费了第"+i+"产品");
       }
   }
}
//产品
class Chicken{
   int id ;//产品编号
   public Chicken(int id){
       this.id = id;
   }
}
// 缓冲区
class SynContainer{
   Chicken[] chickens = new Chicken[10];
   private static int count= 0;
   public  synchronized int getCount(){
       return count;
   }
   public synchronized  void push(Chicken chicken) throws InterruptedException {
       //如果容器满了 就需要等待消费者消费
       if(count == chickens.length){
       this.wait();
       }
       //如果没有满,我们就需要push产品
       chickens[count] = chicken;
       count++;
       this.notify();
   }
   // 消费者消费产品
   public synchronized Chicken pop(){
       Chicken chicken = null;
       //判断缓存池中还有没有产品
       if( count == 0){
           try {
               this.wait();
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }else{
           //如果可以消费
           count -- ;
           chicken  = chickens[count];
       }
       this.notify();
       //吃完了,通知生产者 生产
       return chicken;
   }
}



信号灯法
package lock;

import java.util.TreeMap;

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){
               tv.play("猫和老鼠");
           }else{
               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 {
       //生产者表演,T
       //消费者观看,F
   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.voice = voice;
       this.flag = !this.flag;
       this.notify();
   }

   //观看
   public synchronized void watch(){
       if(flag){
           try {
               this.wait();
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
       System.out.println("观众观看了");
       this.flag = !this.flag;
       this.notify();
   }
}

线程池的使用

在这里插入图片描述

实现代码如下
package lock;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//测试线程池
public class Testpool {


    public static void main(String[] args) {
        //创建服务,创建线程池
        //.newFixedThreadPool 参数为 线程池大小
        ExecutorService service = Executors.newFixedThreadPool(10);
        // 执行
        service.execute(new Mytest());
        service.execute(new Mytest());
        service.execute(new Mytest());
        service.execute(new Mytest());
        // 关闭连接
        service.shutdown();
    }
}

class Mytest implements Runnable{
    @Override
    public void run() {
            System.out.println(Thread.currentThread().getName());
    }
}

线程创建的几种方式

  • Callable和Runable 的区别 前者有返回值 后者没有
package Test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Testnew {
   public static void main(String[] args) {
       new Myclass().start();
       new Thread(new Myclass1()).start();
       FutureTask<Integer> futureTask = new FutureTask<Integer>(new Myclass2());
       new Thread(futureTask).start();

       try {
           Integer integer = futureTask.get();
           System.out.println("Callable的返回值"+integer);
       } catch (InterruptedException e) {
           e.printStackTrace();
       } catch (ExecutionException e) {
           e.printStackTrace();
       }
   }
}
class Myclass extends Thread{
   @Override
   public void run() {
       System.out.println(Thread.currentThread().getName());
       System.out.println("Myclass");
   }
}
class Myclass1 implements  Runnable{

   @Override
   public void run() {
       System.out.println(Thread.currentThread().getName());
       System.out.println("Myclass1");
   }
}
class  Myclass2 implements Callable<Integer>{

   @Override
   public Integer call() throws Exception {

       System.out.println(Thread.currentThread().getName());
       System.out.println("Myclass2");
       return 100;
   }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值