• 线程


      线程是系统调用的最基本单位,多个线程组成进程。电脑中真正执行的线程,我们看到的是进程。

    一:定义

      进程的定义:进程是由一个或多个线程组成。

      线程的定义:CPU调度和分配的最基本单位。

    二:多线程

      定义:在同一个进程中,同时运行多个线程来完成不同的工作。

      原理:CPU不能同时运行多个线程,在一个时间点系统只能运行一个线程。但是在CPU之中线程之间是高速切换的,人是感觉不到的。所以直观上的感觉是同步执行的。

    三:多线程的优点

      01.充分利用CPU的资源   02.提升用户的体验

    四:代码实现多线程

      实现步骤:必须继承Thread 或者实现Runnable接口,然后重写run() 方法,在main方法中实例化Thread对象,调用线程类的start()方法启动线程;

    五:线程的分类

           用户线程: User Thread :默认我们创建的线程就是!
           守护线程: Daemon Thread: 为其他线程提供服务的! GC线程需要我们手动,setDaemon(true)方法设置。

      注意事项:
        01.默认我们创建的线程就是用户线程!通过Thread类中的setDaemon(true)可以转换成守护线程。
        02.只要有用户线程存在,程序就不会终止,所有的用户线程都执行完毕了, 程序会结束所有的守护线程!JVM停止工作!
        03.setDaemon(true)必须在start()之前
        04.守护线程永远不要访问资源!!!因为守护线程随时都可能销毁!

     1 public class DaemonThread implements Runnable {
     2 
     3     @Override
     4     public void run() {
     5         BufferedWriter bw = null;
     6         Writer out = null;
     7         File file = new File("e:/heihei.txt");
     8         try {
     9             System.out.println("进入了 run()");
    10             Thread.sleep(1000); // 保证main先执行完毕
    11             // 获取输出流对象
    12             out = new FileWriter(file);
    13             bw = new BufferedWriter(out);
    14             bw.write("守护线程不可能写进去内容!!看不到我!");
    15         } catch (IOException e) {
    16             e.printStackTrace();
    17         } catch (InterruptedException e) {
    18             e.printStackTrace();
    19         } finally {
    20             try {
    21                 bw.close();
    22                 out.close();
    23             } catch (IOException e) {
    24                 e.printStackTrace();
    25             }
    26         }
    27     }
    28 
    29     public static void main(String[] args) {
    30         Thread thread = new Thread(new DaemonThread(), "守护线程");
    31         // 变成 守护线程
    32         // thread.setDaemon(true);
    33         thread.start();
    34         System.out.println("用户线程===》main结束");
    35     }
    36 }
    守护线程的案例

      01.继承Thread类

     1 /**
     2  * 自己定义的多线程类
     3  * 
     4  * 01.必须继承Thread
     5  * 02.然后重写run() ====>普通的方法
     6  * 03.启动线程调用线程类的start()
     7  */
     8 public class MyThread extends Thread {
     9 
    10     /**
    11      * 重写了Thread类中的 run()
    12      */
    13     @Override
    14     public void run() {
    15         for (int i = 1; i <= 20; i++) {
    16             System.out.println(Thread.currentThread().getName() + "在执行==》" + i);
    17         }
    18     }
    19 
    20     public static void main(String[] args) {
    21         // 创建出来了2个线程对象 然后分别执行 run()
    22         MyThread t1 = new MyThread();
    23         MyThread t2 = new MyThread();
    24         // 分别给两个线程 设置名字
    25         t1.setName("线程1");
    26         t2.setName("线程2");
    27         /*
    28          * t1.run(); t2.run(); 直接调用run()其实就是执行普通方法,那么第一个run()没执行完毕,第二个无法执行
    29          */
    30         // 真正的启动线程,但是线程没有执行! 明明是调用的start(),却是显示的run()方法内容!
    31         // 线程的真正执行是run()
    32         t1.start();
    33         t2.start();
    34 
    35     }
    36 
    37 }
    继承Thread实现

      02.实现Runnable接口

     1 public class MyRunnable implements Runnable {
     2     /**
     3      * 重写了Runnable类中的 run()
     4      */
     5     @Override
     6     public void run() {
     7         for (int i = 1; i <= 20; i++) {
     8             System.out.println(Thread.currentThread().getName() + "在执行==》" + i);
     9         }
    10     }
    11 
    12     public static void main(String[] args) {
    13         // 创建两个线程对象
    14         Thread t1 = new Thread(new MyRunnable(), "线程1");
    15         Thread t2 = new Thread(new MyRunnable(), "线程2");
    16         // 启动线程
    17         t1.start();
    18         t2.start();
    19     }
    20 
    21 }
    实现Runnable接口

      03.实现Callable接口

    (一)线程的生命周期   

       01.新生状态     MyThread t1=new MyThread();  
                Thread t2 = new Thread(new RunnableImp());

       02.就绪状态     调用start()方法,线程就绪,等待分配CPU资源。

       03.运行状态     CPU分配时间片给run方法,线程开始执行run方法线程体代码

          04.阻塞状态    sleep() , 休眠(不释放资源) wait() ,等待(释放系统资源)    yield() , 礼让(静态方法,不一定成功。)                                                                                join(),强制执行至结束线程体代码,才会释放资源。

       05.死亡状态   run()执行完毕正常死亡 ,或者是run()执行过程中,出现了异常(java.lang.IllegalThreadStateException)终止运行,线程死亡。

    (二)关于start()方法,与run()方法的区别:

       01.start方法是是Thread中的方法,调用后会启动线程至就绪状态,底层会调用run方法。继承Runnable接口没有该方法。

       02.run方法是普通的方法,调用run方法是调用普通方法,不会启动多线程。方法体称之为线程体,当CPU分配时间片给线程时,线程才处于运行状态。

    (三)线程的调度方法

      01.设置线程的优先级(有一定的概率调节线程的抢占资源的能力)

     1 /**
     2  * 
     3  * 线程的优先级 Priority
     4  * 默认值是5
     5  * 取值范围是  1-10
     6  * 优先级越高 代表获取CPU资源的概率越高! 并不代表一定高或者一定执行!
     7  * 
     8  */
     9 public class PriorityThread implements Runnable {
    10     @Override
    11     public void run() {
    12         for (int i = 1; i <= 20; i++) {
    13             System.out
    14                     .println(Thread.currentThread().getName() + "======>" + i);
    15         }
    16     }
    17 
    18     public static void main(String[] args) {
    19         // 创建两个线程类对象
    20         Thread t1 = new Thread(new PriorityThread(), "线程1");
    21         Thread t2 = new Thread(new PriorityThread(), "线程2");
    22         System.out.println("t1默认的优先级===》" + t1.getPriority());
    23         System.out.println("t2默认的优先级===》" + t2.getPriority());
    24         // 设置t2的优先级为10 只是一种概率问题 并不能保证 每次都是t2先执行
    25         t2.setPriority(10);
    26         // 启动线程
    27         t1.start();
    28         t2.start();
    29     }
    30 }
    setPriority()方法

      02.强制加入join()方法(一定会先执行完毕调用方法的线程)

     1 /**
     2  * 2.Join   加入新线程
     3  *  让新的线程加入进来,新线程执行完毕之后,其他线程才能执行!
     4  */
     5 public class JoinThread implements Runnable {
     6 
     7     @Override
     8     public void run() {
     9         for (int i = 1; i <= 50; i++) {
    10             System.out
    11                     .println(Thread.currentThread().getName() + "======>" + i);
    12         }
    13     }
    14 
    15     // 测试方法
    16     public static void main(String[] args) {
    17 
    18         Thread t1 = new Thread(new JoinThread(), "新线程1");
    19         // 启动新线程
    20         t1.start();
    21         for (int i = 1; i <= 20; i++) { // 主线程的输出
    22             System.out
    23                     .println(Thread.currentThread().getName() + "======>" + i);
    24             if (i == 5) {
    25                 try {
    26                     System.out.println("T1线程 强制 加入");
    27                     t1.join(); // 阻止main线程
    28                 } catch (InterruptedException e) {
    29                     e.printStackTrace();
    30                 }
    31             }
    32         }
    33     }
    34 }
    join()方法

        03.sleep(long  ms)  Thread类中静态方法,会抛出InterruptedException异常  

     1 /**
     2  * Sleep  线程的休眠     不会释放资源
     3  * 
     4  * sleep(long  ms)  Thread类中方法 
     5        01.线程的休眠,会占着CPU资源不放!其他的线程都无法获取CPU资源!必须等待!
     6        02.long ms指的是在多长时间之后,进入 就绪状态
     7      
     8    wait()是Object类中的方法!
     9             线程wait()的时候,会释放占用的CPU资源!
    10         01.其他的线程无需等待!
    11         02.必须使用notify唤醒才能进入 就绪状态
    12  */
    13 public class SleepThread implements Runnable {
    14     @Override
    15     public void run() {
    16         for (int i = 1; i <= 20; i++) {
    17             System.out
    18                     .println(Thread.currentThread().getName() + "======>" + i);
    19             try {
    20                 Thread.sleep(1000);// 线程休眠一秒
    21             } catch (InterruptedException e) {
    22                 e.printStackTrace();
    23             }
    24         }
    25     }
    26 
    27     public static void main(String[] args) {
    28         // 创建线程类对象
    29         Thread t = new Thread(new SleepThread(), "休眠的线程");
    30         // 线程启动
    31         t.start();
    32     }
    33 }
    sleep()方法

       04.sleep 与 wait 方法的区别

        sleep(long ms) Thread类中方法 (ms表示等待的毫秒数)
          01.线程的休眠,会占着CPU资源不放,其他的线程都无法获取CPU资源。必须等待!
          02.long ms指的是在多长时间之后,进入就绪状态;

        wait()是Object类中的方法! 线程wait()的时候,会释放占用的CPU资源!
          01.其他的线程无需等待!
          02.必须使用notify()唤醒才能进入就绪状态;

      05.yield();礼让方法(不一定有效)

     1 public class YieldThread implements Runnable {
     2 
     3     @Override
     4     public void run() {
     5         for (int i = 1; i <= 50; i++) {
     6             System.out
     7                     .println(Thread.currentThread().getName() + "======>" + i);
     8         }
     9     }
    10 
    11     public static void main(String[] args) {
    12         // 创建线程对象
    13         Thread t = new Thread(new YieldThread(), "老幼病残线程");
    14         // 启动线程
    15         t.start();
    16         for (int i = 1; i <= 50; i++) {
    17             System.out
    18                     .println(Thread.currentThread().getName() + "======>" + i);
    19             if (i % 5 == 0) {
    20                 System.out.println("======main开始礼让了======");
    21                 Thread.currentThread().yield(); // 礼让
    22             }
    23         }
    24     }
    25 }
    yield()礼让方法

      06.设置中断状态。(只是一种标签,不影响线程的运行)

     1 /**
     2  * 设置线程的 中断状态   Interrupt
     3     01.interrupt :      只是设置线程的中断状态,不是终止线程! 线程还会继续执行!
     4     02.isInterrupted:来判断线程是否是 中断状态!
     5     03.interrupted:清除中断状态    interrupted();
     6     04.执行了wait或者sleep,会默认清除中断状态
     7  */
     8 public class InterruptThread implements Runnable {
     9     @Override
    10     public void run() {
    11         // 判断线程是否是中断状态
    12         if (Thread.currentThread().isInterrupted()) {
    13             System.out.println("当前线程是 中断状态!");
    14         } else {
    15             for (int i = 1; i <= 50; i++) {
    16                 System.out.println("线程的状态是===》"
    17                         + Thread.currentThread().isInterrupted());
    18                 System.out.println(Thread.currentThread().getName() + "======>"
    19                         + i);
    20                 if (i == 25) {
    21                     Thread.currentThread().interrupt(); // 线程的中断状态
    22                 }
    23                 if (i == 40) {
    24                     Thread.currentThread().interrupted(); // 清除 线程的中断状态
    25                 }
    26             }
    27         }
    28     }
    29 
    30     public static void main(String[] args) {
    31         // 创建线程对象
    32         Thread t = new Thread(new InterruptThread(), "中断线程");
    33         // 启动线程
    34         t.start();
    35     }
    36 
    37 }
    中断状态 Interrupt
  • 相关阅读:
    程序员的私人外包专家
    目录
    Autumoon Code Library 2008 Beta版 重新发布
    为您的开发团队找个好管家
    .NET编程利器:Reflector for .NET
    3. Extension Methods(扩展方法)
    1. C# 3.0简介
    4. Lambda Expressions (Lambda表达式)与Expressions Tree(表达式树)
    7. Query Expressions(查询表达式)
    6. Anonymous Types(匿名类型)
  • 原文地址:https://www.cnblogs.com/ak666/p/8183865.html
Copyright © 2020-2023  润新知