之前写的代码都是单线程的,只有一个主线程,main方法,即一个程序只有一条从头到尾的执行线索。然而现实世界中的很多过程都具有多条线索同时动作的特性。
java语言的特点是内置了对多线程的支持。
每个进程都有一段专用的内存区域,线程间可以共享相同的内存单元(包括代码和数据)
并利用这些共享单元来实现数据交换,实时通信与必要的同步操作。
Java的多线程就是在操作系统每次分时给java程序一个时间片的CPU时间内,在若干个独立的可控制的线程之间进行切换。
JVM能够充分利用这些CPU,使得java程序在同一时刻获得多个时间片,java程序就可以获得真实的线程并发执行效果。
如果在main方法中创建了其它线程,那么JVM就要在主线程和其它线程之间轮流切换,以保证每个线程都有机会使用cpu资源。
如果main方法中有多个线程,jvm要等所有线程(主线程,和其它线程)都结束才能结束java应用程序。
线程的状态及其生命周期
java里面线程实现由两种方法:
1:继承Thread类及其子类
2:实现runnable接口
新建的线程在完整生命周期里面有四种状态
1.新建
(线程属于创建状态,线程拥有了相应的内存空间和其它资源)
2.运行
线程在创建之后就具备了运行的条件,一旦轮到它来享用cpu资源,即jvm将cpu使用权切换给该进程时,
此线程就可以脱离创建它的主线程独立开始自己的生命周期。
线程创建后仅仅是占有了内存资源,在JVM管理的线程中还没有这个线程,此线程必须调用start()方法(从父类
那里继承的方法)通知jvm,这样jvm就能知道又有一个新线程排队等候切换了。
当JVM将CPU使用权切换给线程时,如果线程是Thread的子类创建的,该类中的run方法会立刻执行。所以,必须在子类中重写父类的run方法,Thread类
的run方法没有具体的内容,程序需要在thread类的子类中重写run方法来覆盖父类的run方法,run方法规定了该线程的具体使命。
在线程没有结束run()方法之前,不要让线程再调用start()方法,否则将发生ILLegalThreadStateException异常。
3.中断
在java中有四种原因的中断:
1.jvm将cpu资源从当前线程切换给其他线程,使本线程让出CPU使用权处于中断状态
2.线程使用cpu资源期间,执行了sleep方法,使当前线程进入休眠状态。sleep方法是thread类的类方法,线程一旦执行了sleep(int millsecond)方法,
就会立刻让出cpu使用权,使当前线程处于中断状态。经过参数millsecond指定的毫秒数之后,该线程会重新进入到线程队列中排队等待cpu资源,以便从
中断处继续运行。
3.线程使用cpu资源期间,执行了wait方法,使当前线程进入到等待状态,等待状态的线程是不会主动进入到线程队列中排队等待cpu资源,必须由其他线
程调用notify方法通知它,使得它重新进入到线程队列中排队等待cpu资源,以便从中断处继续运行。
4.线程使用cpu资源期间,执行某个操作进入阻塞状态,比如执行读写操作引起阻塞。进入阻塞状态时线程不能进入排队队列,只有当引起阻塞的原因消除时,
线程才重新进入线程队列中排队等待cpu资源,以便从原来中断处开始继续运行。
4.死亡
处于死亡状态的线程不具有继续运行的能力。线程死亡的原因有两个,一个是正常运行的线程完成了它的所有工作,即执行完run方法中的所有语句,结束了run方法;
另一个原因是线程被提前强制性终止,即强制run方法结束。所谓死亡状态,就是线程释放了实体,即释放给线程对象的内存
package ThreadMechanism;
public class SpeakHello extends Thread {
public void run(){
for(int i=0;i<10;i++){
System.out.println("Hello"+i);
}
}
}
package ThreadMechanism;
public class SpeakWelcome extends Thread {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Welcome" + i);
}
}
}
package ThreadMechanism;
//java里面多线程运行程序
public class Demo1 {
public static void main(String args[]) {
/* 该过程总共有三个线程,main是主线程,然后主线程执行
然后创建了两个其他线程,此时这两个hello和welcome都具有了相应的内存空间和其它资源
调用start两个线程进入到线程队列中,如果他们得到cpu资源就相应的调用run方法,此时3个线程抢占cpu资源,然后各个线程使用一会cpu资源,直到执行完run方法
主线程*/
SpeakHello hello=new SpeakHello();//创建一个线程1
SpeakWelcome welcome=new SpeakWelcome();//创建一个线程2
welcome.start();//启动线程2
hello.start();//启动线程1
for (int i = 1; i < 10; i++) {
System.out.println("大家好"+i);
}
}
}
这是运行之后结果代码