木舟0基础学习Java的第二十天(线程,实现,匿名有名,休眠,守护,加入,设计,计时器,通信)

avatar
作者
猴君
阅读量:2

多线程

并发执行的技术

并发和并行

并发:同一时间 有多个指令 在单个CPU上 交替执行

并行:同一时间 有多个指令 在多个CPU上 执行

进程和线程

进程:独立运行 任何进程 都可以同其他进程一起 并发执行

线程:是进程中的单个顺序控制流 是一条执行路径 线程又分为单线程和多线程

单线程:

多线程:JVM是多线程 其实就是JVM的主线程和垃圾回收线程在工作 结果在切换着运行

多线程的运行方式:他们拥有相等的运行权限 但运行过程是谁先抢到CPU的运行权限那么谁就先运行

线程的五种状态:新建,就绪,运行,堵塞,死亡

线程的实现:

方式一:继承Thread类

建立一个类继承Thread类 那么这类创建的对象可以并发的作为独立线程运行

继承的好处是可以使用父类中的方法 比较简单

继承的弊端是如果已经有父类了 就不可以再继承了 一个子类只能继承一个父类

public class Demo02 {     public static void main(String[] args) {         MyThread1 m1=new MyThread1();         MyThread2 m2=new MyThread2();         MyThread3 m3=new MyThread3();         //普通方法        /* m1.run();         m2.run();         m3.run();*/         //start开启新线程 内部会根据cpu的分配自动执行run         m1.start();         m2.start();         m3.start();//相当于跑步比赛的发令枪 启动后主线程与其他线程都会等待抢到cpu的执行权         //谁先抢到谁运行     } } //建立一个类继承Thread类 那么这类创建的对象可以并发的作为独立线程运行 class MyThread1 extends Thread{     public void run(){         for (int i = 0; i <10000000 ; i++) {             System.out.println("1号线程");         }     } } class MyThread2 extends Thread{     public void run(){         for (int i = 0; i <10000000 ; i++) {             System.out.println("2号线程");         }     } } class MyThread3 extends Thread{     public void run(){         for (int i = 0; i <10000000 ; i++) {             System.out.println("3号线程");         }     } }

方式二:实现Runnable接口

建立一个类实现Runnable接口

接口的好处是就算实现了其他接口 也可以使用

接口的弊端 操作不便利 需要先获取Thread线程对象

public class Demo03 {     public static void main(String[] args) {         My1 my1=new My1();         Thread t1=new Thread(my1);         My2 my2=new My2();         Thread t2=new Thread(my2);         t1.start();         t2.start();     } } //定义一个类 实现Runnable接口 重新run方法    class My1 implements Runnable{     @Override     public void run() {         for (int i = 0; i <10000000 ; i++) {             System.out.println("1号线程");         }     } }    class My2 implements Runnable{     @Override     public void run() {         for (int i = 0; i <10000000 ; i++) {             System.out.println("2号线程");         }     } }

start()方法把当前线程交给了底层的  ThreadGroup group[]数组管理

Jvm根据随机分配的cpu执行权调用run()  随机分配的cpu执行权是相等概率的

匿名内部类实现线程

方式一:继承Thread类

 public static void main(String[] args) {         new Thread(){             public void run(){                 for(int i=0;i<10000000;i++){                     new Student();                     System.out.println("线程1");             }         }     }.start();         new Thread(){             public void run(){                 for(int i=0;i<10000000;i++){                     new Student();                     System.out.println("线程2");                 }             }         }.start();  }

方式二:实现Runnable接口

  public static void main(String[] args) {         new Thread(new Runnable() {             @Override             public void run() {                 for (int i = 0; i <10000000 ; i++) {                     System.out.println("1号线程");                 }             }         }).start();         new Thread(new Runnable() {             @Override             public void run() {                 for (int i = 0; i <10000000 ; i++) {                     System.out.println("2号线程");                 }             }         }).start();     }

有名内部类实现线程

 public static void main(String[] args) {         Thread t1=new Thread(new Runnable() {             @Override             public void run() {                 for (int i = 0; i <10000000 ; i++) {                     System.out.println("1号线程");                 }             }         });         Thread t2=new Thread(new Runnable() {             @Override             public void run() {                 for (int i = 0; i <10000000 ; i++) {                     System.out.println("2号线程");                 }             }         });         t1.start();         t2.start();     }

设置名字和获取名字(getName() setName())

可以在运行中获取当前线程的对象Thread.currentThread()

public class Demo06 {     public static void main(String[] args) {         Thread t1=new Thread(new Runnable() {             @Override             public void run() {                 for (int i = 0; i <10000000 ; i++) {                     //Thread.currentThread()获取当前运行的线程对象                     //获取名字getName()                     System.out.println(Thread.currentThread().getName());                 }             }         });         Thread t2=new Thread(new Runnable() {             @Override             public void run() {                 for (int i = 0; i <10000000 ; i++) {                     System.out.println(Thread.currentThread().getName());                 }             }         });         //设置名字         t1.setName("线程1");         t1.start();         t2.setName("线程2");         t2.start();     } } 
通过构造方法给线程取名
public class Demo06 {     public static void main(String[] args){         //通过构造方法给线程取名         Thread t1=new Thread(new M1(),"my1");         Thread t2=new Thread(new M2(),"my2");         t1.start();         t2.start();     } } class M1 implements Runnable{      @Override     public void run() {         for (int i = 0; i <100000 ; i++) {            System.out.println(Thread.currentThread().getName());         }     } } class M2 implements Runnable{      @Override     public void run() {         for (int i = 0; i <100000 ; i++) {             System.out.println(Thread.currentThread().getName());         }     } }

休眠

Thread.sleep(100);让当前线程休眠100毫秒

class MM1 implements Runnable{     @Override     public void run() {         for (int i = 0; i <100000 ; i++) {             System.out.println(Thread.currentThread().getName());             try {                 //让当前线程休眠100毫秒                 Thread.sleep(100);             } catch (InterruptedException e) {                 throw new RuntimeException(e);             }         }     } 

守护线程

线程.setDaemon(true);

设置一个线程为守护线程 该线程不会单独执行 当其他非守护线程都执行结束后 再自动退出

public class Demo08 {     public static void main(String[] args) {         M2Thread m2=new M2Thread();         m2.setName("线程2");         m2.start();          M1Thread m1=new M1Thread();         m1.setName("线程1");         m1.start();          //守护线程不会单独执行         Thread1 t=new Thread1();         t.setName("守护线程");         t.setDaemon(true);//设置true为守护线程 主线程结束 守护线程也结束         t.start();     } } class M1Thread extends Thread{     public void run(){         for (int i = 0; i <100 ; i++) {             System.out.println(Thread.currentThread().getName());         }     } } class M2Thread extends Thread{     public void run(){         for (int i = 0; i <100 ; i++) {             System.out.println(Thread.currentThread().getName());         }     } } class Thread1 extends Thread{     public void run(){         for (int i = 0; i <10000 ; i++) {             System.out.println(Thread.currentThread().getName()+i);         }     } } 

加入线程

线程.join(可以限定时间 也可以不限定);

  public static void main(String[] args) {         Thread t1=new Thread("女朋友的电话"){             public void run(){                 for (int i = 0; i <100 ; i++) {                     System.out.println(Thread.currentThread().getName()+i);                 }             }         };         Thread t2=new Thread("老板的电话"){             public void run(){                 for (int i = 0; i <100 ; i++) {                     System.out.println(Thread.currentThread().getName()+i);                     if(i==50){                         try {                             //加入女朋友的线程 基本全面占有cpu执行权                             // t2线程要等待t1线程执行完毕后才可以继续执行                             t1.join();//可以限定时间                             } catch (InterruptedException e) {                                 throw new RuntimeException(e);                             }                         }                 }             }         };         t1.start();         t2.start();     }

礼让(了解)

Thread.yield();//让出cpu的执行权给别的线程

设置优先级:(优先级1-10 默认为5)

线程.setPriority(10);

同步(同步锁,同步代码块)

注意:开发中尽量不要嵌套同步代码块 可能会死锁
关键字:synchronized(同步锁使用的多)
public class Test {     String s="123";     //同步锁 在方法中加synchronized关键字     //public synchronized void show1(){}       public synchronized void show1(){         System.out.print("我");         System.out.print("爱");         System.out.print("学");         System.out.print("习");         System.out.println("-----------");     }     public void show2(){         //同步代码块synchronized(s锁对象){}         //多个同步代码块如果使用相同的锁对象 那么他们就是同步的      synchronized(s){          System.out.print("想");         System.out.print("睡");         System.out.print("觉");         System.out.println("===========");}     } }

线程安全

synchronized线程安全  没有synchronized线程不安全

Vector线程安全  ArrayList线程不安全

Stringbuffer安全  stringBuilder不安全

HashTable安全  HashMap不安全

设计模式

单例设计模式

public class Single {     private Single(){//私有构造方法 不让其他类new对象     }    static Single s=new Single(); }
    public static void main(String[] args) {         Single s1=Single.s;         Single s2=Single.s;         System.out.println(s1==s2);//true         Single s3=null;//对象可以被修改         Single s4=Single.s;         System.out.println(s3==s4);//false     }
饿汉式(直接加载)

节约时间 浪费空间(例如:安卓手机应用可以在后台运行)

一旦被加载进来 就创建好了对象 不管是否使用 都在内存中
public class Single1 {     private Single1(){//私有构造方法 不让其他类new对象     }    static Single1 s=new Single1();     //饿汉式     public static Single1 getInstance(){         //一旦被加载进来 就创建好了对象 不管是否使用 都在内存中         return s;     } }
public static void main(String[] args) {         Single s1=Single.getInstance();         Single s2=Single.getInstance();         System.out.println(s1==s2);//true     }
懒汉式(延迟加载)

节约空间 浪费时间(例如:苹果手机应用不挂后台)

什么时候用 什么时候才创建
public class Single2 {     private Single2(){}     public static Single2 s=null;     //懒汉式     public static Single2 Instance(){         //需要的时候才创建对象         if(s==null){             s=new Single2();         }         return s;     } }

Runtime类单例(查API)

每个 Java 应用程序都有一个Runtime类实例 使应用程序能够与其运行的环境相连接 可以通过 getRuntime方法获取当前运行时。

应用程序不能创建自己的 Runtime类实例

 public static void main(String[] args) {         Runtime r=Runtime.getRuntime();         try {             //r.exec("mspaint");//打开画图             //r.exec("notepad");//打开记事本             //r.exec("shutdown -s -t 6000");//6000秒后自动关机             //r.exec("shurdown -a");//取消自动关机             //r.exec("百度去");         } catch (IOException e) {             throw new RuntimeException(e);         }     }

Timer类(计时器)

用来定时执行程序的类
public class MyTask extends TimerTask {     @Override     public void run() {         System.out.println("起床了");     } }
 public static void main(String[] args) {         //用来定时执行程序的类         Timer t=new Timer();         //5秒后执行任务         t.schedule(new MyTask(),new Date(System.currentTimeMillis()+5000));         //5秒后执行任务 每隔1秒重复执行         t.schedule(new MyTask(),new Date(System.currentTimeMillis()+5000),1000);     }

线程通信(等待,唤醒)

必须在同步代码块中 使用同步锁对象调用(唤醒 等待 唤醒 等待)代码交替运行

并发执行时 默认情况下 cpu的执行权 是随机的 谁先抢到谁先执行

如果希望有规律的执行 就可以用线程通信

notify唤醒 wait等待

案例:两个方法交替

public class TestThread2 {     public synchronized void print(){         System.out.print("我");         System.out.print("爱");         System.out.print("学");         System.out.print("习");         System.out.println("-----------");         this.notify();//唤醒正在等待的线程         try {             this.wait();//让当前线程等待 让出cpu执行权 进入就绪状态         } catch (InterruptedException e) {             throw new RuntimeException(e);         }     }     public synchronized void show(){         System.out.print("想");         System.out.print("睡");         System.out.print("觉");         System.out.println("===========");         this.notify();//唤醒正在等待的线程         try {             this.wait();//让当前线程等待 让出cpu执行权 进入就绪状态         } catch (InterruptedException e) {             throw new RuntimeException(e);         }     } }
 public static void main(String[] args) {         TestThread2 tt2=new TestThread2();         new Thread(){             public void run(){                while(true){ tt2.print();}             }         }.start();         new Thread(){             public void run(){                 while(true){ tt2.show();}             }         }.start();     }

案例:三个和三个以上方法交替

public class TestThread3 {     boolean b1=true;     boolean b2=false;     boolean b3=false;     public synchronized void show1() {         if (b3) {             System.out.print("我");             System.out.print("爱");             System.out.print("学");             System.out.print("习");             System.out.println("-----------");         }         b1 = true;         b3 = false;         this.notifyAll();//唤醒所有正在等待的线程         try {             this.wait();//让当前线程等待 让出cpu执行权 进入就绪状态         } catch (InterruptedException e) {             throw new RuntimeException(e);         }     }     public synchronized void show2(){         if(b1){             System.out.print("想");             System.out.print("睡");             System.out.print("觉");             System.out.println("===========");         }         b2=true;         b1=false;         this.notifyAll();//唤醒所有正在等待的线程         try {             this.wait();//让当前线程等待 让出cpu执行权 进入就绪状态         } catch (InterruptedException e) {             throw new RuntimeException(e);         }     }     public synchronized void show3(){         if(b2){             System.out.print("想");             System.out.print("吃");             System.out.print("饭");             System.out.println("~~~~~~~~~~~");         }         b2=false;         b3=true;         this.notifyAll();//唤醒所有正在等待的线程         try {             this.wait();//让当前线程等待 让出cpu执行权 进入就绪状态         } catch (InterruptedException e) {             throw new RuntimeException(e);         }     } }
 public static void main(String[] args) {         TestThread3 tt3=new TestThread3();         new Thread(){             public void run(){                 while(true){                     tt3.show1();                 }             }         }.start();         new Thread(){             public void run(){                 while(true){                     tt3.show2();                 }             }         }.start();         new Thread(){             public void run(){                 while(true){                     tt3.show3();                 }             }         }.start();     }

wait和sleep区别

wait():释放锁 等待并释放锁让别的线程运行

sleep():不释放锁 在指定的时间抱着锁睡 时间一到马上醒来

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!