• Java基础(九)多线程


    一、线程和进程

    进程(Process)

    1、是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。

    2、在早期面向进程设计的计算机结构中,进程是程序的基本执行实体。

    3、在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体

     线程(thread)

    1、看成是进程中的最小单元。

    2、一个进程中可以有1个或者多个线程(其实也就是一小段代码)。

    3、 线程其实也可以看成是一个轻量级的进程(比如1个进程只有1个线程)。

    4、在单个程序中同时运行多个线程完成不同的工作,称为多线程

    CPU:执行任务是以线程为单位;会在不同的时间片上不断的切换线程。

    二、启动线程两种方式

    1、启动线程两种方式:

    1、通过继承Thread

     1 /**
     2  * 继承thread类
     3  */
     4 public class ThreadMusic extends Thread {
     5     @Override
     6     public void run(){
     7         synchronized (this){  //同步
     8             for (int i =0; i< 100; i ++){
     9                 System.out.println(this.getName() + "------听音乐------" + i);
    10             }
    11         }
    12     }
    13 }

    2、实现 Runnable 接口

    区别一个类如果继承了其他类,就无法在继承Thread类,在Java中,一个类只能继承一个类,而一个类如果实现了一个接口,还可以实现其他接口,接口是可以多实现的,所以说Runable 的扩展性更强

     1 /**
     2  * 实现runnable接口
     3  */
     4 public class RunnableMusic implements Runnable {
     5     @Override
     6     public void run() {
     7         synchronized (this){ //同步
     8             for (int i =0; i< 100; i ++){
     9                 System.out.println(Thread.currentThread().getName() + "------听音乐------" + i);
    10             }
    11         }
    12     }
    13 }

    2、启动线程流程

    创建启动线程的方式一:继承Thread

          ① 明确需要把什么事情封装成线程对象;

          ② 自定义类 extends Thread

          ③ 覆写run方法: 写①

          ④ 创建自定义对象t

          ⑤ 启动线程 t.start();

    创建启动线程方式二:实现Runnable接口

          ①明确需要把什么事情封装成线程对象;

          ② 自定义类 implements Runnable接口

          ③ 覆写run方法: 写①

          ④ 创建自定义对象t

          ⑤ 启动线程 new Thread(t).start();

    测试线程:

     1 public class testThread {
     2     /**
     3      * 测试threadMusic
     4      */
     5     @Test
     6     public void testThread(){
     7         ThreadMusic music = new ThreadMusic();
     8         music.start();
     9     }
    10 
    11     /**
    12      * 测试threadMusic
    13      */
    14     @Test
    15     public void testRunnable(){
    16         RunnableMusic runnableMusic = new RunnableMusic();
    17         Thread thread = new Thread(runnableMusic);
    18         thread.start();
    19     }
    20 }

    3、线程方法

    1、Thread类的方法

    static void sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)

     1 /**
     2  * 测试sleep方法
     3  */
     4 public class SleepTest{
     5     public static void main(String[] args) throws InterruptedException {
     6         for(int i = 1; i<11; i++ ){
     7             System.out.println(i);
     8             Thread.sleep(1000); //休眠1秒
     9         }
    10     }
    11 }

    2、获取Thread的名称

     1 /**
     2  * 继承thread类
     3  */
     4 public class ThreadMusic extends Thread {
     5     @Override
     6     public void run(){
     7         synchronized (this){
     8             for (int i =0; i< 100; i ++){
     9                 System.out.println(this.getName() + "------听音乐------" + i); //获取Thread的名称
    10             }
    11         }
    12     }
    13 }

    3、获取Runnable的名称

     1 /**
     2  * 实现runnable接口
     3  */
     4 public class RunnableMusic implements Runnable {
     5     @Override
     6     public void run() {
     7         synchronized (this){ //同步
     8             for (int i =0; i< 50; i ++){
     9                 //获取Runnable的名称, currentThread()方法,返回当前正在执行的线程引用
    10                 System.out.println(Thread.currentThread().getName() +"------听音乐------" + i);
    11             }
    12         }
    13     }
    14 }

    结论:继承和实现获取线程名称方式是不一样。

    4、Thread方法(jion)

      void join() 方法 :等待该线程终止。

     1 /**
     2  * JoinThread线程
     3  */
     4 public class JoinThread extends Thread {
     5     @Override
     6     public void run() {
     7         for (int i = 0; i < 100; i++) {
     8             System.out.println("JoinThread --->" + i);
     9             try{
    10                 Thread.sleep(1);  //JoinThread再休眠一秒,为了交替出现更有规律
    11             } catch (InterruptedException e){
    12                 e.printStackTrace();
    13             }
    14         }
    15     }
    16 }

      测试 join 方法:

     1 /**
     2  * 测试join方法
     3  */
     4 public class JoinDemo {
     5     public static void main(String[] args) throws InterruptedException {
     6         JoinThread joinThread = new JoinThread();
     7         joinThread.start();
     8 
     9         for (int i = 0; i < 100; i++) {
    10             System.out.println("main ---> " + i);
    11             if(i == 10){
    12                 joinThread.join(); //等待该线程终止,才继续执行main线程
    13             }
    14             Thread.sleep(1);  //主线程模拟网络延迟
    15         }
    16     }
    17 }

    理解:joinThread.join(): 当主线程执行到10的时候,JionThread线程加进来,等待JionThread线程全部执行完,然后才继续执行主线程。

    另外除了jion()方法以外,还有jion(long millils) 方法 (等待线程执行的固定时间,然后时间一到,jion失效)。

    4、线程优先级

        高优先级线程的执行优先于低优先级线程;并不是绝对的,可能优先级高的线程比优先级低的线程先执行,只能说,高优先级的线程优先执行的几率更多;

      (比如两个线程,一个优先级高,一个优先级低,如果一共运行一个小时,优先级高的线程执行远远大于优先级低的,但是并不是说,优先级高的先执行完,在执行优先级低的)。

    方法:

    int   getPriority()  返回线程的优先级 

    void  setPriority() 更改线程的优先级

    1 public class PriorityDemo {
    2     public static void main(String[] args) {
    3         Thread thread = Thread.currentThread();
    4         System.out.println(thread.getPriority());  //获取优先级
    5         thread.setPriority(8); //设置优先级
    6         System.out.println(thread.getPriority());
    7     }
    8 }

      自定义线程的默认优先级和创建它的环境的线程优先级一致。

    5、守护线程

       每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。

      后台线程:指为其他线程提供服务的线程,也称为守护线程。JVM的垃圾回收线程就是一个后台线程。

    Thread类提供的方法:

    方法: void setDaemon(boolean on) 将该线程标记为守护线程或用户线程。

    方法:isDaemon()  测试该线程是否为守护线程。

     1 public class DaemonDemo {
     2     public static void main(String[] args) {
     3         //获取主线程
     4         Thread thread = Thread.currentThread();
     5         System.out.println(thread.isDaemon());  //false  非后台线程
     6         //尝试变更为后台线程
     7         thread.setDaemon(true);
     8         //活动的线程不能设置后台线程,主线程不能设置为后台线程。
     9         System.out.println(thread.isDaemon());  //Exception in thread "main" java.lang.IllegalThreadStateException
    10     }
    11 }

    结论::自定义线程的默认状态和环境有关,后台线程中创建的线程默认是后台线程,前台线程中创建的线程为前台线程。

    6、线程同步

     Java中3种同步方式:

    1、同步代码块

          synchronized (同步监听对象){

             需要同步的代码

          }

    注意事项: 同步监听对象 可以是任意的对象,但是多个线程来访问的,此对象必须是同一对象,一般写this,或者当前类的字节码对象(类名.class),或者相关的业务对象。

    2、同步方法写法:

       借助于方法的{} 把synchronized直接作为方法的修饰符;

    3、同步方式-锁(lock)

  • 相关阅读:
    vue里的样式添加之类名改动 和style改动
    vue里的样式添加之行间样式
    vue 里filter的基本用法
    Binary Tree Inorder Traversal
    Course Schedule 解答
    Topological Sorting
    Maximum Depth of Binary Tree 解答
    Clone Graph 解答
    Java Keyword -- super
    Binary Tree Zigzag Level Order Traversal 解答
  • 原文地址:https://www.cnblogs.com/zt19994/p/8432190.html
Copyright © 2020-2023  润新知