moc 发表于 2019-1-13 14:22:36

Java030-线程基础

本帖最后由 moc 于 2019-1-13 14:21 编辑

1、简介
进程: 正在运行的程序,是系统进行资源分配和调用的独立单位,每一个进程都有它自己的内存空间和系统资源,详见入口。
线程: 是进程中的单个顺序控制流,是一条执行路径,线程不能独立存在,依附于进程。
Java程序至少有两个线程:主线程 + 垃圾回收线程
线程的生命周期:

新建状态:
      使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
就绪状态:
      当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
运行状态:
      如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
阻塞状态:
      如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
      ① 等待阻塞: 运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
      ② 同步阻塞: 线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
      ③ 其他阻塞: 通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
死亡状态:
      一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。
2、线程实现方式1: 继承Thread类
步骤:
      ① 自定义类MyThread继承Thread类;
      ② MyThread类里面重写run();
      ③ 创建MyThread类的对象,即线程对象;
      ④ 启动线程,调用线程对象的start()方法。
注意:
      ① run():仅仅是封装被线程执行的代码,直接调用是普通方法
      ② start():首先启动了线程,然后再由jvm去调用该线程的run()方法
获取设置线程名:
public static Thread currentThread() ------------>返回当前正在执行的线程对象
public final String getName()--------------------->获取线程的名称      
public final void setName(String name) --------->设置线程的名称
举例:
// 线程类
public class MyThread extends Thread {      
      public MyThread() {
      }
      
      public MyThread(String name){
                super(name);
      }

      @Override
      public void run() {
                for (int x = 0; x < 20; x++) {
                        System.out.println(x);
                }
      }
}
// 线程测试类
public class MyThreadDemo {
      public static void main(String[] args) {
                // 创建线程对象 --- 无参构造+setXxx()
                MyThread my1 = new MyThread();
                my1.setName("Ubuntu");   //调用方法设置名称
                my1.start();
               
                // 创建线程对象 --- 带参构造方法
                MyThread my2 = new MyThread("Centos");
                my2.start();
               
                System.out.println(Thread.currentThread().getName());
      }
}3、线程控制
1. 守护线程(后台线程)
守护线程与普通线程的唯一区别是:当JVM中所有的线程都是守护线程的时候,JVM就可以退出了;如果还有一个或以上的非守护线程则不会退出。(以上针对正常退出,调用System.exit必定会立即退出)
方法:   public final void setDaemon(boolean on)
MyThread my3 = new MyThread("RedHat");
my3.setDaemon(true);
my3.start();2. 线程休眠
Thread类静态方法,让线程进程一定时间的阻塞状态,时间结束后处于就绪状态争夺CPUI执行权。
方法:   public static void sleep(long millis)
3. 线程加入
等待该线程终止,在进行其他线程的执行。
方法:   public final void join()
MyThread my4 = new MyThread("openSuSE");
MyThread my5 = new MyThread("Linux Mint");
my4.start();
try {
      my4.join();
}
catch (InterruptedException e) {
      e.printStackTrace();
}
my5.start();4. 线程礼让
Thread类静态方法,暂停当前正在执行的线程对象,并执行其他线程。
让多个线程的执行更和谐,但是不能靠它保证一个线程一次。
方法:   public static void yield()
public class ThreadYield extends Thread {
      @Override
      public void run() {
                for (int x = 0; x < 100; x++) {
                        System.out.println(getName() + ":" + x);
                        Thread.yield();    // 线程礼让
                }
      }
}5. 中断线程
把线程的状态终止,并抛出一个InterruptedException。
方法:   public void interrupt()
MyThread my6 = new MyThread("Debian");
my6.start();
// 线程超过三秒不醒过来,就中断线程 (最多允许该线程允许3s)
try {
      Thread.sleep(3000);
      my6.interrupt();
}
catch (InterruptedException e) {
      e.printStackTrace();
}6. 线程优先级
      ① 每一个 Java 线程都有一个优先级< 默认NORM_PRIORITY(5)>,这样有助于操作系统确定线程的调度顺序。
        ② Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。
        ③ 具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器资源。但是,线程优先级不能保证线程执行的顺序,而且非常依赖于平台。
方法:
public final int getPriority()--------------------------> 返回线程对象的优先级
public final void setPriority(int newPriority) --------> 更改线程的优先级。
MyThread my7 = new MyThread("Fedora");
MyThread my8 = new MyThread("Solus OS");

System.out.println(my7 .getPriority());
my8.setPriority(2);

my7.start();
my8.start();4、线程实现方式2: 实现Runnable接口
步骤:
        ① 自定义类MyRunnable实现Runnable接口;
        ② 重写run()方法;
        ③ 创建MyRunnable类的对象;
        ④ 创建Thread类的对象,并把③步骤的对象作为构造参数传递。
// Runnable接口实现类
public class MyRunnable implements Runnable {
        @Override
        public void run() {
                for (int x = 0; x < 100; x++) {
                        // 由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接的使用
                        System.out.println(Thread.currentThread().getName() + ":" + x);
                }
        }
}
// Runnable实现类测试
public class MyRunnableDemo {
        public static void main(String[] args) {
                MyRunnable my = new MyRunnable();// 创建MyRunnable类的对象

                // 创建Thread类的对象,并把③步骤的对象作为构造参数传递               
                Thread t1 = new Thread(my);   // Thread(Runnable target)
                t1.setName("Windows");;
                Thread t2 = new Thread(my, "Linux");   // Thread(Runnable target, String name)

                t1.start();
                t2.start();
        }
}
页: [1]
查看完整版本: Java030-线程基础