一、进程、线程基础概念
1. 什么是进程?什么是线程?
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。比如:QQ.exe运行就是一个进程。
线程可以理解成是在进程中独立运行的子任务。比如,QQ.exe 运行时有很多子任务同时在运行,视频线程、下载文件线程、发送消息线程等等。
多线程是异步的,所以 代码里面线程的顺序并不是线程的执行顺序,线程调用是随机的。
2. 线程的实现方式:A. 继承 Thread 类 B. 实现 Runnable 接口
There are two ways to create a new thread of execution. 源码中明确标注,两种方式实现线程
从 Thread 源码来看,Thread 类也是实现了 Runnable 接口。这两种方式创建的线程在工作时性质一样的,只不过继承 Thread 不支持多继承,而实现 Runnable 则可以避免这个问题。
A. 继承 Thread 类
public class MyThread extends Thread {
@Override
public void run() {
super.run();
System.out.println("My Thread");
}
}
B. 实现 Runnable 接口
/**
* @ClassName MyThreadRunnable
* @Description 实现 Runnable 接口
*/
public class MyThreadRunnable implements Runnable {
public void run() {
System.out.println("My Thread Runnable");
}
}
/**
* @ClassName Test2
* @Description 测试实现 Runnable 接口的线程
*/
public class Test2 {
public static void main(String[] args) {
MyThreadRunnable mtr = new MyThreadRunnable();
Thread thread = new Thread(mtr);
thread.start();
System.out.println("运行结束!");
}
/*
运行结果:
运行结束!
My Thread Runnable
*/
}
3. 线程是一个子任务,CPU以不确定的方式调用线程中的 run() 方法,所以线程 run() 方法的执行和 程序中代码顺序无关(后面会有线程状态可解释)。看下面的例子:
public class Test {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
System.out.println("运行结束!");
/* 结果:
* 运行结束!
* My Thread
*/
}
}
下面再举一个例子(CPU以不确定的方式调用线程中的 run() 方法):
/**
* @ClassName MyThread
* @Description 线程随机挂起
*/
public class MyThread extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
int time = (int) (Math.random() * 1000);
Thread.sleep(time);
System.out.println("run=" + Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* @ClassName Test
* @Description 测试线程被随机调用的特性,main线程也随机被挂起
*/
public class Test {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.setName("myThread");
thread.start();
for (int i = 0; i < 10; i++) {
int time = (int) (Math.random() * 1000);
Thread.sleep(time);
System.out.println("main=" + Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/*
运行结果:可见线程(main线程 和 MyThread线程)在被挂起后,再次被运行是随机的
run=myThread
main=main
run=myThread
main=main
main=main
main=main
run=myThread
run=myThread
run=myThread
main=main
run=myThread
main=main
run=myThread
run=myThread
main=main
run=myThread
run=myThread
main=main
main=main
main=main
*/
}
例子3(线程 run() 方法的执行和 程序中代码顺序无关):
/**
* @ClassName MyThread2
* @Description 测试start()代码顺序和线程被调用的顺序
*/
public class MyThread2 extends Thread {
private int i;
public MyThread2(int i) {
super();
this.i = i;
}
@Override
public void run() {
System.out.println(i);
}
}
/**
* @ClassName Test2
* @Description
*/
public class Test2 {
public static void main(String[] args) {
MyThread2 my1 = new MyThread2(1);
MyThread2 my2 = new MyThread2(2);
MyThread2 my3 = new MyThread2(3);
MyThread2 my4 = new MyThread2(4);
MyThread2 my5 = new MyThread2(5);
MyThread2 my6 = new MyThread2(6);
MyThread2 my7 = new MyThread2(7);
MyThread2 my8 = new MyThread2(8);
MyThread2 my9 = new MyThread2(9);
MyThread2 my10 = new MyThread2(10);
my1.start();
my2.start();
my3.start();
my4.start();
my5.start();
my6.start();
my7.start();
my8.start();
my9.start();
my10.start();
}
/*
运行结果:可以看出,线程被调用的顺序并不是按照 start()方法的代码顺序来的
2
3
6
7
10
1
5
9
4
8
*/
}