> 文章列表 > 多线程,线程终止,Thread,Runnable接口,多个子线程

多线程,线程终止,Thread,Runnable接口,多个子线程

多线程,线程终止,Thread,Runnable接口,多个子线程

  1. 程序:为完成特定任务,用某种语言编写的一组指令的集合。简单说就是代码
  2. 进程:指运行的程序,操作系统就会为进程分配内存空间
  3. 进程是程序的一次执行过程,或是正在运行的一个程序。是动态过程:有它自身的产生,存在,和消亡的过程
  4. 线程由进程创建的,是线程的一个实体
  5. 一个进程可以拥有多个线程
  6. 单线程:同一个时刻,只允许执行一个线程
  7. 多线程:同一个时刻,可以执行多个线程,qq可以打开多个聊天窗口,迅雷同下载多个文件
  8. 并发:同一个时刻,多个任务交替执行,造成一种"貌似同时"的错觉,简单的说,单核cpu实现的多任务就是并发
  9. 并行:同一个时刻,多个任务同时执行。多核cpu可以实现并行
  10. 创建线程的两种方式
    1. Thread
      package com.jshedu.cpu_;/* @author Mr.jia* @version 1.0*/public class Thread01 {public static void main(String[] args) {//创建一个Cat对象,可以当做线程使用了Cat cat = new Cat();//为什么用start方法,调用run方法,不直接调用run方法//如果直接调用run(),那么就是main线程里的一个普通方法,并没有//真正启动一个线程。也不会主线程子线程交替执行了。主线程会阻塞在这里等run//方法执行完之后在执行主线程/*源码(1)public synchronized void start() {start0();}(2)//start0() 是本地方法,是JVM调用, 底层是c/c++实现//真正实现多线程的效果, 是start0(), 而不是 runprivate native void start0();*/cat.start();//启动线程,main的子线程//当main线程启动一个子线程,主线程不会阻塞,会继续执行//主线程和子线程是交替执行for (int i = 0; i < 60; i++) {System.out.println("主线程"+i);//主线程try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
      }
      /*
      1.当一个类继承Thread类,该类就可以当做线程使用
      2.我们会重写run方法,写上自己的业务代码
      3.run Thread类 实现了 Runnable 接口的run方法@Overridepublic void run() {if (target != null) {target.run();}}*/
      class Cat extends Thread{int time=0;@Overridepublic void run() {//重写run方法,写上自己的业务逻辑while (true){//该进程每隔1秒在控制台输出System.out.println("喵喵喵"+(++time));//该线程休眠1秒ctrl+alt+ttry {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if(time == 80){break;//当time达到指定次数,线程就退出了}}}
      }
      

      用start(),不用run()

    2. java是单继承,某些情况下一个类可能已经继承了某个父类,这时在用继承Thread类方法来创建线程显然不可能了。

    3. 通过实现Runnable接口来创建线程

    4. package com.jshedu.cpu_;/* @author 韩顺平* @version 1.0* 通过实现接口Runnable 来开发线程*/
      public class Thread02 {public static void main(String[] args) {Dog dog = new Dog();//dog.start(); 这里不能调用start,因为是实现Runnable接口里面没有start()//创建了Thread对象,把 dog对象(实现Runnable),放入ThreadThread thread = new Thread(dog);//设计模式:代理模式thread.start();//        Tiger tiger = new Tiger();//实现了 Runnable
      //        ThreadProxy threadProxy = new ThreadProxy(tiger);
      //        threadProxy.start();}
      }class Animal {
      }class Tiger extends Animal implements Runnable {@Overridepublic void run() {System.out.println("老虎嗷嗷叫....");}
      }//线程代理类 , 模拟了一个极简的Thread类
      class ThreadProxy implements Runnable {//你可以把Proxy类当做 ThreadProxyprivate Runnable target = null;//属性,类型是 Runnable@Overridepublic void run() {if (target != null) {target.run();//动态绑定(运行类型Tiger)}}public ThreadProxy(Runnable target) {this.target = target;}//先走这public void start() {start0();//这个方法时真正实现多线程方法}//在走这public void start0() {run();}
      }class Dog implements Runnable { //通过实现Runnable接口,开发线程int count = 0;@Overridepublic void run() { //普通方法while (true) {System.out.println("小狗汪汪叫..hi" + (++count) + Thread.currentThread().getName());//休眠1秒try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if (count == 10) {break;}}}
      }
      

      就是有的类继承了其他的类,这时在用继承Thread类方法来创建线程显然不可能了。现在实现Runnable接口来创建线程,Runnable里有run方法重写,Runnable里没有start方法,通过构造器传入参数【Runnable target,的实现类也行】,调用该类的方法

    5. 多个子线程案例

      package com.hspedu.threaduse;/* @author 韩顺平* @version 1.0* main线程启动两个子线程*/
      public class Thread03 {public static void main(String[] args) {T1 t1 = new T1();T2 t2 = new T2();Thread thread1 = new Thread(t1);Thread thread2 = new Thread(t2);thread1.start();//启动第1个线程thread2.start();//启动第2个线程//...}
      }class T1 implements Runnable {int count = 0;@Overridepublic void run() {while (true) {//每隔1秒输出 “hello,world”,输出10次System.out.println("hello,world " + (++count));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if(count == 60) {break;}}}
      }class T2 implements Runnable {int count = 0;@Overridepublic void run() {//每隔1秒输出 “hi”,输出5次while (true) {System.out.println("hi " + (++count));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if(count == 50) {break;}}}
      }
      

      这里面main线程把Thread1和Thread2启动后就停掉了,没有过多的功能

  11. 继承Thread vs 实现Runnable的区别

    1. 从java的设计来看,通过继承Thread或者实现Runnable接口来创建线程本质没有区别,都是实现了Runnable接口

    2. 实现Runnable接口方式更加适合多个线程共享一个资源的情况,并且避免了单继承的限制,建议使用。

  12. 售票系统案例

  13. 线程终止:启动一个线程t,要求在main线程中去停止线程t,请编程实现

    package com.hspedu.exit_;/* @author 韩顺平* @version 1.0*/
    public class ThreadExit_ {public static void main(String[] args) throws InterruptedException {T t1 = new T();t1.start();//如果希望main线程去控制t1 线程的终止, 必须可以修改 loop//让t1 退出run方法,从而终止 t1线程 -> 通知方式//让主线程休眠 10 秒,再通知 t1线程退出System.out.println("main线程休眠10s...");Thread.sleep(10 * 1000);t1.setLoop(false);}
    }class T extends Thread {private int count = 0;//设置一个控制变量private boolean loop = true;@Overridepublic void run() {while (loop) {try {Thread.sleep(50);// 让当前线程休眠50ms} catch (InterruptedException e) {e.printStackTrace();}System.out.println("T 运行中...." + (++count));}}public void setLoop(boolean loop) {this.loop = loop;}
    }