进程是计算机系统资源分配的最小单位,一个进程可以有一个或者多个线程。
线程是计算机运行的最小单位,一个线程只属于一个进程。
Java 提供了三种创建线程的方法:
首先是run()方法里面创建一个进程,然后main方法中开了一个主线程,主线程接着开了一个子线程。主线程与子线程的执行是互不影响的。只有所有的线程都结束了进程才结束。
public class test_thread extends Thread {//主线程:main主线程public static void main(String[] args) throws InterruptedException {Cat cat = new Cat();cat.start();//主线程中又开启了一个子线程//主线程开启子线程后,不会阻塞:主线程和子线程会交替执行System.out.println("主线程的名字:"+Thread.currentThread().getName());for (int i=0;i<10;i++){System.out.println("主线程执行 i=" + i);Thread.sleep(1000);}}}//业务需求:
//1. 当Cat类继承了 Thread 类, 该类就可以当做线程使用
//2. 我们会重写 run 方法, 写上自己的业务代码
//3. run Thread 类 实现了 Runnable 接口的 run 方法
class Cat extends Thread{//创建一个线程,Cat类继承了Threadint times=0;//创建了一个进程:@Overridepublic void run() {//重写run方法while (true){System.out.println("喵喵叫。。。。"+(++times) +" "+"子线程名:"+Thread.currentThread().getName());//休眠1stry {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//如果等于8次,退出循环:if (times == 8){break;}}}
}
为什么开启子线程需要用start(),而不直接调用run();因为如果直接调用run()方法,此时run()方法就是一个普通的方法。此时的线程就main线程,这时主线程不会开启子线程,只会顺序执行,也就变成了单线程了。
public class test_thread02 {public static void main(String[] args) throws InterruptedException {Dag dag = new Dag();dag.run();//这时是执行了一个普通的方法,不会开启一个子线程;这时执行的线程是主线程;//此时就变成了单线程了,就是main线程;System.out.println("当前的主线程:"+Thread.currentThread().getName());for (int i=0;i<9;i++){System.out.println("输出i ="+ i );Thread.sleep(1000);}}
}class Dag extends Thread{//创建一个线程,Cat类继承了Threadint times=0;//创建了一个进程:@Overridepublic void run() {//重写run方法while (true){System.out.println("喵喵叫。。。。"+(++times) +" "+"子线程名:"+Thread.currentThread().getName());//休眠1stry {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//如果等于8次,退出循环:if (times == 8){break;}}}
}
喵喵叫。。。。1 子线程名:main
喵喵叫。。。。2 子线程名:main
喵喵叫。。。。3 子线程名:main
喵喵叫。。。。4 子线程名:main
喵喵叫。。。。5 子线程名:main
喵喵叫。。。。6 子线程名:main
喵喵叫。。。。7 子线程名:main
喵喵叫。。。。8 子线程名:main
当前的主线程:main
输出i =0
输出i =1
输出i =2
输出i =3
输出i =4
输出i =5
输出i =6
输出i =7
输出i =8
public class test_runnable {public static void main(String[] args) {//创建子线程:Tiger tiger = new Tiger();//因为runnable接口没有start方法:所以需要动态代理的方式:Thread thread = new Thread(tiger);thread.start();//开启子线程:System.out.println("当前主线程的名字是:"+Thread.currentThread().getName());}
}class Tiger implements Runnable{//实现了Runnable接口:int times=0;@Overridepublic void run() {while (true){System.out.println("老虎饿了"+(++times) + " "+"当前的线程名是:"+Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if (times == 10){break;}}}
}
使用实现runnable接口来实现多个线程:
public class test_runnable02 {public static void main(String[] args) {//开启子线程:thread01 thread01 = new thread01();thread02 thread02 = new thread02();Thread td1 = new Thread(thread01);Thread td2 = new Thread(thread02);td1.start();td2.start();}
}class thread01 implements Runnable{//第一个线程int count=0;@Overridepublic void run() {while (true){System.out.println("hello thread01" + " "+(++count) +" "+ "当前的进程名字是:"+Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if (count == 10){break;}}}
}class thread02 implements Runnable{int count=0;//第二个线程:@Overridepublic void run() {while (true){System.out.println("hello thread02" +" "+(++count)+" "+"当前进程名字是:"+ Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if (count == 10){break;}}}
}
hello thread01 1 当前的进程名字是:Thread-0
hello thread02 1 当前进程名字是:Thread-1
hello thread01 2 当前的进程名字是:Thread-0
hello thread02 2 当前进程名字是:Thread-1
hello thread01 3 当前的进程名字是:Thread-0
hello thread02 3 当前进程名字是:Thread-1
hello thread01 4 当前的进程名字是:Thread-0
hello thread02 4 当前进程名字是:Thread-1
hello thread01 5 当前的进程名字是:Thread-0
hello thread02 5 当前进程名字是:Thread-1
hello thread01 6 当前的进程名字是:Thread-0
hello thread02 6 当前进程名字是:Thread-1
hello thread01 7 当前的进程名字是:Thread-0
hello thread02 7 当前进程名字是:Thread-1
hello thread01 8 当前的进程名字是:Thread-0
hello thread02 8 当前进程名字是:Thread-1
hello thread01 9 当前的进程名字是:Thread-0
hello thread02 9 当前进程名字是:Thread-1
hello thread01 10 当前的进程名字是:Thread-0
hello thread02 10 当前进程名字是:Thread-1
本质上两者没有区别,但是实现Runnable接口更适合多个线程共享资源,并且避免了单继承的机制。