乐趣区

Java线程的浅层理解

线程(Thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

进程(Process)是计算机中已运行程序的实体。进程为曾经是分时系统的基本运作单位。

一个进程可以有很多线程,每条线程并行执行不同的任务。


示例代码:

(来自慕课网的代码实例)

  • 主类:
import java.io.*;

public class Stage extends Thread {public static void main(String[] args) {new Stage().start();}

    public void run(){System.out.println("欢迎观看隋唐演义");

        try {Thread.sleep(1000);
        } catch (InterruptedException e1) {e1.printStackTrace();
        }

        System.out.println("大幕徐徐拉开");
        
        try {Thread.sleep(1000);
        } catch (InterruptedException e1) {e1.printStackTrace();
        }
        
        System.out.println("话说隋朝末年,隋军与农民起义军杀得昏天黑地...");
        

        ArmyRunnable armyTaskOfSuiDynasty = new ArmyRunnable(); 
        ArmyRunnable armyTaskOfRevolt = new ArmyRunnable();
        
        /**
         * 创建两个线程
         */
        Thread  armyOfSuiDynasty = new Thread(armyTaskOfSuiDynasty,"隋军");
        Thread  armyOfRevolt = new Thread(armyTaskOfRevolt,"农民起义军");
        
        /**
         * 启动线程,让军队开始作战
         */
        armyOfSuiDynasty.start();
        armyOfRevolt.start();
        
        try {Thread.sleep(1000);
        } catch (InterruptedException e) {e.printStackTrace();
        }
        
        System.out.println("正当双方激战正酣,半路杀出了个程咬金");
        
        Thread mrCheng = new KeyPersonThread();
        mrCheng.setName("程咬金");
        
        System.out.println("程咬金的理想就是结束战争,使百姓安居乐业!");
        
        /**
         * 停止前两个线程
         */
        armyTaskOfSuiDynasty.keepRunning = false;
        armyTaskOfRevolt.keepRunning = false;
        
        try {Thread.sleep(2000);
        } catch (InterruptedException e) {e.printStackTrace();
        }
        
        mrCheng.start(); // 开始第三个线程
                
        try {mrCheng.join(); // 新进程加入,join() 方法会在该线程结束之前一直占用 CPU} catch (InterruptedException e) {e.printStackTrace();
        }
        
        
        System.out.println("战争结束,人民安居乐业,程先生实现了积极的人生梦想,为人民作出了贡献!");
        System.out.println("谢谢观看隋唐演义,再见!");
        
    }    
}
  • 辅助类:
class ArmyRunnable implements Runnable {

    volatile boolean keepRunning = true; // volatile 单独说明

    @Override
    public void run() {while(keepRunning){for(int i=0;i<5;i++){System.out.println(Thread.currentThread().getName()+"进攻对方["+i+"]");
                
                Thread.yield(); // yield() 方法单独说明
            }
                    
        }
        
        System.out.println(Thread.currentThread().getName()+"结束了战斗!");

    }

}

class KeyPersonThread extends Thread {public void run(){System.out.println(Thread.currentThread().getName()+"开始了战斗!");
        for(int i=0;i<10;i++){System.out.println(Thread.currentThread().getName()+"左突右杀, 攻击隋军...");
        }
        System.out.println(Thread.currentThread().getName()+"结束了战斗!");
    }
}

join() 方法的详细说明:

  1. 在“主线程 main”中通过 new ThreadA(“t1”) 新建“线程 t1”。接着,通过 t1.start() 启动“线程 t1”,并执行 t1.join()。
  2. 执行 t1.join()之后,“主线程 main”会进入“阻塞状态”等待 t1 运行结束。“子线程 t1”结束之后,会唤醒“主线程 main”,“主线程”重新获取 cpu 执行权,继续运行。

volatile 变量的说明:

  1. (适用于 Java 所有版本)读和写一个 volatile 变量有全局的排序。也就是说每个线程访问一个 volatile 作用域时会在继续执行之前读取它的当前值,而不是(可能)使用一个缓存的值。(但是并不保证经常读写 volatile 作用域时读和写的相对顺序,也就是说通常这并不是有用的线程构建)。
  2. (适用于 Java5 及其之后的版本)volatile的读和写建立了一个 happens-before 关系,类似于申请和释放一个互斥锁。

yield()方法的说明:

会使当前线程由执行状态变为让步状态,但不代表下次执行的线程必然是其它的线程,该方法执行后当前线程会处于竞争状态,因此下次执行的线程依然可能是上次执行的线程(这里假设各个线程优先级相同)。

退出移动版