Java学习-第一部分-第二阶段-第七节:泛型

打印 上一主题 下一主题

主题 913|帖子 913|积分 2739

线程

笔记目录:(https://www.cnblogs.com/wenjie2000/p/16378441.html)
程序(program)
是为完成特定任务、用某种语言编写的一组指令的集合。简单的说:就是我们写的代码
进程

  • 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存空间。当我们使用迅雷,又启动了一个进程,操作系统将为迅雷分配新的内存空间。
  • 进程是程序的一次执行过程,或是正在运行的一个程序。是动态过程:有它自身的产生、存在和消亡的过程
线程介绍

什么是线程

  • 线程由进程创建的,是进程的一个实体2.一个进程可以拥有多个线程(例如迅雷中 多个下载任务同时进行)
  • 坦克大战(每个敌人坦克就是一个线程)[后面会把多线程加入到坦克大战中,学以致用]
其他相关概念

  • 单线程:同一个时刻,只允许执行一个线程
  • 多线程:同一个时刻,可以执行多个线程,比如:一个qq进程,可以同时打开多个聊天窗口,一个迅雷进程,可以同时下载多个文件
  • 并发:同一个时刻,多个任务交替执行,造成一种“貌似同时”的错觉,简单的说,单核cpu实现的多任务就是并发。

  • 并行:同一个时刻,多个任务同时执行。多核cpu可以实现并行。
    1. public class Test {
    2.     public static void main(String[] args) {
    3.         Runtime runtime = Runtime.getRuntime();
    4.         //获取当前电脑的cpu数量/核心数
    5.         int cpuNums = runtime.availableProcessors();
    6.         System.out.println("当前有CPU个数"+cpuNums);
    7.     }
    8. }
    复制代码
线程使用

创建线程的两种方式
在java中线程来使用有两种方法。

  • 继承Thread类,重写run方法
  • 实现Runnable接口,重写run方法

继承Thread

线程应用案例1-继承Thread类

  • 请编写程序,开启一个线程,该线程每隔1秒。在控制台输出“啪瞄,我是小猫咪'
  • 对上题改进:当输出80次唶瞄,我是小猫咪,结束该线程
  • 使用JConsole监控线程执行情况,并画出程序示意图!

  1. public class Test {
  2.     public static void main(String[] args) throws InterruptedException {
  3.         //创建Cat对象,可以当做线程使用
  4.         Cat cat = new Cat();
  5.         /*
  6.             (1)
  7.             public synchronized void start() {
  8.                 start0();
  9.             }
  10.             (2)
  11.             //start0()是本地方法,是JVM调用,底层是c/c++实现
  12.             //真正实现多线程的效果,是start0(),而不是 run
  13.             private native void start0();
  14.         */
  15.         cat.start();//启动线程
  16.         //cat.run();//run方法就是一个普通的方法,没有真正的启动一个线程,就会把run方法执行完毕,才向下执行
  17.         //说明:当main线程启动一个子线程 Thread-0,主线程不会阻塞,会继续执行//这时主线程和子线程是交替执行..
  18.         System.out.println("主线程继续执行" + " 线程名" + Thread.currentThread().getName());//线程main
  19.         for (int i = 0; i < 60; i++) {
  20.             System.out.println("主线程i=" + i);
  21.             //让主线程休眠
  22.             Thread.sleep(1000);
  23.         }
  24.     }
  25. }
  26. //说明
  27. //1。当一个类继承了 Thread 类,该类就可以当做线程使用
  28. //2.我们会重写 run方法,写上自己的业务代码
  29. //3.run Thread类实现了Runnable接口的run方法
  30. /*
  31.     @Override
  32.     public void run() {
  33.         if (target != null) {
  34.             target.run();
  35.         }
  36.     }
  37. */
  38. class Cat extends Thread {
  39.     int times = 0;
  40.     @Override
  41.     public void run() {
  42.         while (true) {
  43.             //该线程每隔1秒。在控制台输出“瞄瞄,我是小猫咪"
  44.             System.out.println("瞄瞄,我是小猫咪" + " 线程名" + (++times) + Thread.currentThread().getName());//让该线程休眠1秒ctrl+alt+t
  45.             try {
  46.                 Thread.sleep(1000);
  47.             } catch (InterruptedException e) {
  48.                 e.printStackTrace();
  49.             }
  50.             if (times == 80) {
  51.                 break; //当times 到80,退出while,这时线程也就退出..
  52.             }
  53.         }
  54.     }
  55. }
复制代码
start()方法原理

实现Runnable

线程应用案例2-实现Runnable接口
说明

  • java是单继承的,在某些情况下一个类可能已经继承了某个父类,这时在用继承Thread类方法来创建线程显然不可能了。
  • java设计者们提供了另外一个方式创建线程,就是通过实现Runnable接口来创建线程
线程使用应用案例-实现Runnable接口
应用案例
请编写程序该程序可以每隔1秒。在控制台输出“hi!”,当输出10次后,自动退出。请使用实现Runnable接口的方式实现。
  1. public class Test {
  2.     public static void main(String[] args) throws InterruptedException {
  3.         Dog dog = new Dog();
  4.         //dog.start();这里不能调用start
  5.         //创建了Thread对象,把 dog对象(实现Runnable),放入Thread
  6.         Thread thread = new Thread(dog);
  7.         thread.start();
  8.     }
  9. }
  10. class Dog implements Runnable {//通过实现Runnable接口,开发线程
  11.     int count = 0;
  12.     @Override
  13.     public void run() {//普通方法
  14.         while (true) {
  15.             System.out.println("小狗汪汪叫..hi" + (++count) + Thread.currentThread().getName());
  16.             try {
  17.                 Thread.sleep(1000);
  18.             } catch (InterruptedException e) {
  19.                 e.printStackTrace();
  20.             }
  21.             if (count>10){
  22.                 break;
  23.             }
  24.         }
  25.     }
  26. }
复制代码
这里底层使用了设计模式【代理模式】
以下为代码模拟 实现Runnable接口开发线程的机制(可以用来代替上述代码中的Thread类的功能)此处只是模拟来展示原理,并不能实际创建新线程,任然是执行main线程
  1. //线程代理类,模拟了一个极简的Thread类
  2. class ThreadProxy implements Runnable {//你可以把Proxy类当做 ThreadProxy
  3.     private Runnable target = null;//属性,类型是 Runnable
  4.     @Override
  5.     public void run() {
  6.         if (target != null) {
  7.             target.run();
  8.         }
  9.     }
  10.     public ThreadProxy(Runnable target) {
  11.         this.target = target;
  12.     }
  13.     public void start() {
  14.         start0();
  15.     }
  16.     public void start0() {
  17.         run();
  18.     }
  19. }
复制代码
继承Thread vs 实现Ruunnable的区别

  • 从java的设计来看,通过继承Thread或者实现Runnable接口来创建线程本质上没有区别,从jdk帮助文档我们可以看到Thread类本身就实现了Runnable接口
  • 实现Runnable接口方式更加适合多个线程共享一个资源的情况,并且避免了单继承的限制(建议使用Runnnable接口)
思考:[售票系统],编程模拟三个售票窗口售票100张,分别使用继承 Thread和实现Runnable方式,并分析有什么问题?
  1. public class Test {
  2.     public static void main(String[] args) {
  3. //测试
  4.         SellTicket01 sellTicket01 = new SellTicket01();
  5.         SellTicket01 sellTicket02 = new SellTicket01();
  6.         SellTicket01 sellTicket03 = new SellTicket01();
  7.         //这里会出现超卖问题
  8.         sellTicket01.start();//启动售票线程
  9.         sellTicket02.start();//启动售票线程
  10.         sellTicket03.start();//启动售票线程
  11.     }
  12. }
  13. class SellTicket01 extends Thread {
  14.     private static int ticketNum = 100;//让多个线程共享ticketNum
  15.     @Override
  16.     public void run() {
  17.         while (true) {
  18.             if (ticketNum <= 0) {
  19.                 System.out.println("售票结束...");
  20.                 break;
  21.             }
  22.             //休眠50毫秒
  23.             try {
  24.                 Thread.sleep(50);
  25.             } catch (InterruptedException e) {
  26.                 e.printStackTrace();
  27.             }
  28.             System.out.println("窗口" + Thread.currentThread().getName() +"售出一张票"
  29.                     + "剩余票数=" + (--ticketNum));
  30.         }
  31.     }
  32. }
复制代码
线程常用方法

常用方法第一组


  • setName    //设置线程名称,,使之与参数name相同
  • getName    //返回该线程的名称
  • start    //使该线程开始执行;Java虚拟机底层调用该线程的start0方法
  • run    //调用线程对象 run方法;
  • setPriprity    //更改线程的优先级
  • getPriority    //获取线程的优先级
  • sleep    //在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
  • interrupt    //中断线程
注意事项和细节

  • start底层会创建新的线程,调用run。run 就是一个简单的方法调用,本身不会启动新线程
  • 线程优先级的范围
  • sleep:线程的静态方法,使当前线程休眠
  • interrupt:中断线程,但并没有真正的结束线程。所以一般用于中断正在休眠线程
    1. public class Test {
    2.     public static void main(String[] args) throws InterruptedException {
    3.         T t1 = new T();
    4.         Thread thread = new Thread(t1);
    5.         thread.start();
    6.         //如果希望main线程去控制t1 线程的终止,必须可以修改 loop
    7.         // 让t1退出run方法,从而终止t1线程->通知方式
    8.         //让主线程休眠10秒,再通知t1线程退出
    9.         System.out.println("main线程休眠10s");
    10.         Thread.sleep(5 * 1000);
    11.         t1.setLoop(false);
    12.     }
    13. }
    14. class T implements Runnable {
    15.     boolean loop = true;//步骤1:定义标记变量,默认为true@Override
    16.     int count=0;
    17.     @Override
    18.     public void run() {
    19.         while (loop) {//步骤2:将loop作为循环条件
    20.             try {
    21.                 Thread.sleep(50);//让当前线程休眠10ms
    22.             } catch (InterruptedException e) {
    23.                 e.printStackTrace();
    24.             }
    25.             System.out.println("AThread运行中...."+(++count));
    26.         }
    27.     }
    28.     //步骤3:提供公共的set方法,用于更新loop
    29.     public void setLoop(boolean loop) {
    30.         this.loop = loop;
    31.     }
    32. }
    复制代码
常用方法第二组


  • yield:线程的礼让。让出cpu,让其他线程执行,但礼让的时间不确定,所以也不一定礼让成功(例:Thread.yield();//礼让自己使用cpu资源,不指定某一特定线程。具体用法看下面代码)
  • join:线程的插队。插队的线程一旦插队成功,则肯定
    先执行完插入的线程所有的任务(例:t2.join();//指定特定的某一线程先完成任务,再执行自己的工作)

案例:创建一个子线程,每隔1s输出hello,输出20次,主线程每隔1秒,,输出hi,输出20次.要求:两个线程同时执行,当主线程输出5次后,就让子线程运行完毕,主线程再继续
[code]public class Test {    public static void main(String[] args) throws InterruptedException {        T2 t2 = new T2();        t2.start();        for (int i = 1; i

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

老婆出轨

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表