JAVA-多线程

1、 线程和进程

进程和线程的区别?

什么是进程

​ 任务管理器中看到的各种,如:QQ、网易云音乐、Steam、dffice办公软件、IDEA、任务管理器自己等等

​ 这一些我们称之为进程。

什么是线程

​ 线程是每一个进程中可能存在多个线程多并执行,

​ 我们生活中的例子:田径比赛,整体看作进程,每位参赛选手看作线程,只有当所有参赛选手都跑完,这一个进程才算完全结束。

​ 一个进程是由一个或多个线程组成的。

​ 魔兽世界中可能存在多个线程,每个线程都可以回去到相同的魔兽世界的资源,比如用用户登录信息。但是他不可能获取别的进程,如网易云音乐。魔兽世界中的线程不能区播放网易云音乐进程中的歌曲。

2、 多线程

 

比如,一个进程开始运作,同时开辟四条线程:做登录、打广告、放视频、最后加载页面。

CPU存在单核单线程CPU,多核多线程CPU。

首先如果你的CPU是支持多线程,俺么我们开盘多线程肯定很好理解。

但是如果你的CPU是单线程CPU此时你就只能单线程么?

答案是否定的

 

3、 Thread类

  public static void main(String[] args) {
      //通过Thread.currentThread()方法获取当前的线程
      Thread t=Thread.currentThread();
      //通过线程对象t调用他的getName()方法,过去当前线程的名称
      System.out.println(t.getname());
      //通过setName可以修改线程的名称
      t.setName("这个main方法的名字被我改了");
      System.out.println(t.getName());
  }

手动创建自己的线程有两种方法:

第一个继承Thread类

第二个实现Runnable接口

4、继承Thread类实现多线程


  
  //第一步继承Thread类
  public class MyThread1 extends Thread{
      public MyThread1(String name){
          super(name);
      }
      
      //第二步,我们通过重写run()方法来实现线程的自定义
      @override
      public void run(){
          for(int i=0;i<1000;i++){
              System.out.println(Thread.currentthread().getName()+i);
          }
      }
      
      public static void main(String[] args){
          //第三步,实例化我们继承的Thread类的类
          MyThread1 myThread1=new MyThread1("我的第一个线程");
          MyThread1 myThread2=new MyThread1("我的第二个线程");
          MyThread1 myThread3=new MyThread1("我的第三个线程");
          //第四步,通过start()方法去调用run()方法的内容
          //虽然我们没有去重写start()方法,但是Thresd类会通过start方法调用run方法
          //只有通过start()方法调用才是真正起到了开辟一个新线程
          //如果是用run()调用,那么依旧是在主线中跑的
          myThread1.start();
          myThread2.start();
          myThread3.start();
          
          for(int i=0;i<1000;i++;){
              System.out.println(Thread.currentThread().getName()+i);
          }
      }
  }
 

5、 实现Runnable接口实现多线程


  
  //第一步,新增一个类实现Runnable接口
  public class MyThread2 implements Runnable{
      //第二步,重写run()方法
      @Override
      public void run(){
          for(int i=0;i<10000;i++){
              System.out.printlm(Thread.currentThread().gatName()+i)
          }
      }
      
      public static void main(String[] args){
          //第三步,将实现Runnable接口的类实例化
          MyThread2 myThread1=new MyThread2();
          MyThread2 myThread2=new MyThread();
          MyThread2 myThread3=new MyThread();
          
          //第四步,将实例化的对象参数传入Thread类实例化的对象
          Thread t1=new Thread(myThread1,"1线程");
          Thread t2=new Thread(myThread2,"2线程");
          Thread t3=new Thread(myThread3,"3线程");
          
          //第三步和第四步可一步实现,一步到位
          //Thread t1=new Thread(new MyThread(),"1线程");
          //Thread t2=new Thread(new MyThread(),"2线程");
          //Thread t3=new Thread(new MyThread(),"3线程");
          
          //第五步,通过Thread类的实例化对象调用他的start()方法
          t1.start();
          t2.start();
          t3.start();
          
          for(int i=1;i<10000;i++){
              System.out.println(Thread.currentThread().getName()+i);
          }
      }
  }
​ 可以使用Landba表达式去实例化一个匿名内部类Runable接口,之后正常创建线程

  public static void main(String[] args){
      //匿名内部类实现
      Thread t=new Thread(new Runnable);{
      @Override
          public void run(){
              for(int i=0;i<10;i++){
                  System.out.println(Thread.currentThread().getName()+i);
              }
          }
      });
      //也可以通过Lamdba表达式
      Thread t1=new Thread(()->{
          for(int i=;i<0;i++){
              System.out.println(Thread.currentThread().getName()+i);
          }
      });
  ​
      t.setName("匿名内部类的方式调用");
      t1.setName("Lamdba表达式实现接口");
      t.start();
      t1.start();
  }
 

6、 继承Thread类和实现Runnable接口的比较

总结一下,无论你是Thread类的继承,还是Runnable接口的实现,你都需要通过Thread这个类的start();方法区实现多线程的使用.如果你是调用的 run();方法,那么你肯定是单线程。

第二点,Thread类和Runnable接口实现的不同,由于java类只存再单继承,多实现,所以我们优先推荐大家使用接口的方式调用多线程,因为你继承了thread类,你就无法继承别的类,可能这个方法对于后期的代码扩展维护存在部分的问题。

切记,实现Runnable接口是将他当作参数传入新的Thread类中!!!!

7、 start()和run()的区别

调用start()方法

 

调用run()方法

 

8、 生命周期

 

9、 线程调度方法

9.1、 stop(); 停止线程

​ 这个方法会让线程进入死亡状态。注意!这个方法是过时的方法,我们不应该这样做,这样去做有可能会造成你线程中的数据丢失,因为我们run方法后面可能存在保存数据的内容,但是由于某些奇奇怪怪的原因,在没有执行到保存数据的方法的时候,县城就被其余地方杀死了,进入死亡状态,期间的所有数据均出现丢失。

  public static void main(String[] args){
      public MyThread1(String name){
          super(name);
      }
      #Override
      public void run(){
          System.out.print("线程启动");
          for(int i=0;i<100000;i++){
              System.out.println(Thread.currentThread().getName()+i);
          }
          System.out.print("线程代码执行结束");
      }
      
      public static void main(String[] args){
          MyThread1 m=new MyThread1("test");
          m.start();
          try{
              //线程休眠500ms(毫秒)
              Thread.sleep(500);
          }catch(InterruotedException e){
              e.printStackTrace();
          }
          //类似于任务管理器结束进程,没保存的数据就丢失了
          m.stop();
      }
  }

科学停止线程方法:


  public class Mythread3 extends Thread{
      //我们有一个标记位置,这个线程的开关
      static boolean flag=true;
      @Override
      public void run(){
          while(true){
              if(!flag){
                  //进入这个方法块,说明我们的代码线程被关闭了,我们可以再这里执行保存功能
                  System.out,println("执行保存代码");
                  return;
              }
              System.out.println("------------------------------")
          }
      }
      public static void main(String[] args){
          MyThread3 thread3=new MyThread();
          thread3.strat();
          try{
              Thread.sleep(2000);
          }catch(InterruptedException e){
              e.printStackTrace();
          }
          //相当于关上我们线程的开关
          MyThread3.flag=flase;
      }
  }

9.2、 设置优先级 setPriority();


  public static void main(String[] args){
      MyThread1 thread1=new MyThread("1号");
      MyThread1 thread1=new MyThread("2号");
      MyThread1 thread1=new MyThread("3号");
      MyThread1 thread1=new MyThread("4号");
      //最大值不能大于MAX_PRIORITY(10),最小值不能小于MIN_PRIORITY(1)
      //默认是5
      //数字越大代表越容易抢到资源,但是不是说一定优先级高
      thread1.setPriority(10);
      thread2.setPriority(Thread.MAX_PRIORITY);//10
      thread3.setPrioriy(6);
      thread4.setPriority(Thread.MIN_PRIORITY);//1
      thread1.start();
      thread2.start();
      thread3.start();
      thread4.start();
  }

9.3、 线程休眠 sleep();

相当于让线程进入阻塞状态


  public static void main(String[] args){
      MyThread1 m=new MyThread1("test");
      m.start();
      try{
          //线程休眠500ms(毫秒)
          //线程休眠属于静态方法,如果我们是使用对象去调用,他依旧会把他视同为类
          //如
          m.sleep(500);
          //此时是使用m对象调用这个方法,但是编译之后还是会变成如下代码;
          //Thread.sleep(500);
          //所以休眠的线程依旧是当前写在这里的线程,而不是m这个对象的线程
      }catch(InterruptedException e){
          e.printStackTrace();
      }
      //类似于任务管理器结束进程,没保存的数据丢失了
      m.stop();
      }
  }

9.4、 强制运行(阻塞所有其他人)join();

join();方法相当于阻塞当前的线程,至于哪个对象调用,说明需要等到对应对象跑完(进入死亡阶段),那他才能继续跑


  public static void main(String[] args){
      MyThread1 myThread1=new MyThread1("我的第一个线程");
      MyThread1 myThread2=new MyThread1("我的第二个线程");
      myThread1.start();
      myThread2.start();
      for(int i=0;i<10000;i++){
          System.out.println(Thread.currentThread().getName()+i);
          if(i==5000){
              try{
                  //相当于当主线程的循环执行到i==5000时,我们让当前线程阻塞
                  //让myThread1加入
                  //知道myThread1跑完了才会让
                  //相当于我们对mian方法发令“你别动,然他先加入”
                  myThread1.join();
                  
                  //这一行代码写不写的区别在于:
                  //看我们main线程何时从堵塞状态恢复到就绪状态
                  //如果不写,那就是myThread1跑完,他就回复就绪
                  //然后main和myThread2一起争夺资源
                  //如果写了,就是要等myThread2跑完
                  myThread2.join();
              }catch(InterruptedException e){
          e.printStackTrace();
              }
          }
      }
  }

9.5、 线程的礼让 yield ();

相当于让线程进入就绪状态

  public class Mythread4 extends Thread{
      @Override
      public void run(){
          for(int i;i<10;i++){
              if(i%3==0){
                  System.out.println("线程象征性执行了一次礼让");
                  Thread.yield();
              }
              System.out.println("thread4对象的"+i);
          }
      }
      public static void main(String[] args){
          MyThread4 myThread4=new MyThread4();
          thread4.setPriority(1);
          thread4.start();
          for(int i=0;i<100;i++){
              System.out.println("mian方法的"+i);
          }
      }
  }

由于是进入了就绪状态,所以其实还是有点看运气,不知道是哪个时点

9.6、 打断睡眠 interrup();

  public class Mythread5 extends Thread{
      @Override
      public void run(){
          for(int i=0;i<1000;i++){
              //写睡眠时间或者类似这种写法需要毫秒值时,建议使用如下写法
              try{
                  //会执行到i==500时休眠一年
                  Thread.sleep(1000*60*60*24*365);
              }catch(InterruptedExceptoin e){
                  System.out.println("这里的睡眠被中断了,需要做什么你就做什么。");
              }
          }
          System.out.println("thread5对象的"+i);
      } 
      public static void main(String[] args){
          MyThread5 myThread5=new MyThread4();
          thread5.start();
          try{
              Thread.sleep(5000);
          }catch(InterrupedException e){
              e.printStackTrace();
          }
          //执行把thread5叫醒
          //相当于让我们的thread5再执行睡眠时抛出一个InterruptedException
          //通过try-catch异常处理机制,实现睡眠被唤醒
          thread5.interrupt();
      }
  }

10、 需要解决线程并发是发生的数据冲突问题

​ 如果我们需要使用多线程,这些数据存在共同性,可能两个线程同时操作一个数据,比如银行取钱,2张卡是一个账户,两个线程对应一个账号,这个时候我们就要考虑会不会因为并发(多个线程异步执行)会造成数据影响问题。

同步执行

​ 我跑,你跟在我的后头跑,我跑到终点,你再跑到重点

异步执行

​ 我跑我的,你跑你的,我在错做数据的时候你也在操作

异步的效率更高,但是由于数据是异步的,无法同步,所以需要考虑数据是否会影响结果


  public class RobTicket implements Runnable{
      private int count=10;//总票数
      private int num=1;//当前票
      
      @Override
      public void run(){
          while(true){
              if(count>0){
                  System.out.println(Thread.currentThread().getName()+
                                     "抢到了第"+num+"张票,余票数还剩"+count+"张");
                  num++;
                  count--;
              }else{
                  System.out.println(Thread.currentTread().getName()+
                                     "没抢到票,因为没票了");
                      return;
              }
              try{
                  Tread.sleep(500);
              }catch(InterrupedException e){
                  e.printStckTracr();
              }
          }
      }
      
      public static void main(String[] args){
          RobTicket robTicket =new RobTicket();
          Thread t1=new Thread(robTicket);
          Thread t2=new Thread(robTicket);
          Thread t3=new Thread(robTicket);
          
          t1.setName("淘票票");
          t2.setName("12306");
          t3.setName("大麦网");
          
          t1.start();
          t2.start();
          t3.start();
      }
  }

11、synchronized关键字解决问题


  public class RobTicket1 implements Runnable{
      private int count=10;//总票数
      private int num=1;//当前票
      
      @Override
      public void run (){
          while(count>0){
              sale();
          }
      }
      
      public synchronized void sale(){
          if(count>0){
              System.out.println(Thread.currentThread().getName()+
                                 "抢到了第"+num+"张票,余票数还剩"+count+"张");
              num++;
              count--;
          }else{
              System.out.println(Thread.currentTread().getName()+
                                 "没抢到票,因为没票了");
                  return;
          }
          try{
              Tread.sleep(500);
          }catch(InterrupedException e){
              e.printStckTracr();
          }
      }
  ​
      
      public static void main(String[] args){
          RobTicket robTicket =new RobTicket();
          Thread t1=new Thread(robTicket);
          Thread t2=new Thread(robTicket);
          Thread t3=new Thread(robTicket);
          
          t1.setName("淘票票");
          t2.setName("12306");
          t3.setName("大麦网");
          
          t1.start();
          t2.start();
          t3.start();
      }
  }

第二种写法:

注意核心难点 :synchronized() 括号内的内容!!!

  
  public class RobTicket2 implements Runnable{
      private int count=10;//总票数
      private int num=1;//当前票
      
      @Override
      public void run(){
          while(true){
              //()括号中写的内容比较复杂
              //这里面需要写的是一个对象,我们会根据这个对象的内存地址去创建一把锁
              //如果你们的这个对象是一样的,那么,就需要使用这一把锁;如果是不一样的,就相当于不同的锁
              //是否相同对象,如果是相同的对象就要一起排队,如果是不同的对象就比用一起排队
              synchronized(this){
                  if(count>0){
                      System.out.println(Thread.currentThread().getName()+
                                         "抢到了第"+num+"张票,余票数还剩"+count+"张");
                      num++;
                      count--;
                  }else{
                      System.out.println(Thread.currentTread().getName()+
                                         "没抢到票,因为没票了");
                          return;
                  }
                  try{
                      Tread.sleep(500);
                  }catch(InterrupedException e){
                      e.printStckTracr();
                  }
              }
          }
  }
      
      public static void main(String[] args){
          RobTicket robTicket =new RobTicket();
          Thread t1=new Thread(robTicket);
          Thread t2=new Thread(robTicket);
          Thread t3=new Thread(robTicket);
          
          t1.setName("淘票票");
          t2.setName("12306");
          t3.setName("大麦网");
          
          t1.start();
          t2.start();
          t3.start();
      }
  }

12、 附加内容

java.util.concurrent提供了一系列方便并发编程的类

阻塞队列BolckingQueue

延迟队列DelayQueue

闭锁CountDownQueue

线程池ExcutorService

…………

第三种创建线程的方式

Callable:能够获取线程执行结果——该结构使用call调用,可以存在返回值,而Runnable时无返回值的

冷山寒水
关注 关注
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
写文章

热门文章

  • JAVA-面向对象 1835
  • JAVA-基础⑦二维数组与排序 1818
  • JAVA-IO流① 575
  • JAVA-基础⑤Debug与嵌套循环 552
  • CSS基础② 508

最新评论

  • JVAV-基础②标识符与运算符

    二哈喇子!: 是不是java啊

  • CSS基础③

    冷山寒水: Typora许可证过期之后重装导致前端的笔记全都丢了,只能用备份的图片了

  • CSS基础③

    babbfqb93: 直接放图片有点水啊

最新文章

  • JAVA- Maven
  • JAVA-正则表达式
  • JAVA-XML&JSON
2022年32篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

玻璃钢生产厂家南关区玻璃钢雕塑工程施工陕西玻璃钢雕塑生产厂家滁州雕塑玻璃钢玻璃钢消防卡通形象雕塑玻璃钢家具昭通市玻璃钢雕塑怎么样永州玻璃钢牌匾雕塑茂名玻璃钢人像雕塑山西玻璃钢卡通雕塑批发玻璃钢斑马雕塑视频商场中空创意美陈舟山学校玻璃钢雕塑安庆动物玻璃钢雕塑白银仿真玻璃钢雕塑公司南阳哪里有玻璃钢人物雕塑厂家武汉花瓣型玻璃钢花盆延安人物玻璃钢雕塑公司玻璃钢卡通公仔人物雕塑长治玻璃钢泡沫雕塑商场导视美陈湖艺玻璃钢校园雕塑赣州创意玻璃钢雕塑设计来宾玻璃钢雕塑小品潮州玻璃钢昆虫雕塑定制银行商场美陈展示节日道具秦皇岛玻璃钢花盆厂家广东商场节庆美陈雕塑工厂新县玻璃钢雕塑厂家濮阳玻璃钢室外雕塑定做厂家成品玻璃钢雕塑摆件生产香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化