
- 线程就是内存中的一个对象,线程并不是调用start方法之后就立刻开始执行而是表示准备好了(Cpu可能正在执行其他线程),应该进行排队。当Cpu有时间片了,就分配给这个线程开始执行,如果到时间了,那么停止运行,重新排队。重复这个过程,直至运行完毕。
- 如果运行中出现状况,那么会停止运行,进入阻塞状态,直至解除才能进入就绪状态,准备排队。如果没有解除那么就会中止。
- 简言之就是 创建(new Thread) 就绪(start()) 执行(run()) ( 阻塞 解除阻塞 ) 就绪
- 执行反复循环直至执行完毕 挂起包括就绪和阻塞状态
- 当线程试图获得一个对象的锁,而该锁被其他线程持有,那么当前线程进入阻塞状态
当调用wait或join方法时,会进入等待状态
当一个线程被阻塞或终止时,另一个线程被设置为运行状态。当一个线程重新激活时,线程调度器会检查它是否具有比当前运行线程更高的优先级,如果是这样,那么线程调度器会从当前运行线程中挑选一个,剥夺其运行权,选择一个新的线程继续运行 - 这些方法是Thread类的静态和动态方法,如果想调用静态方法 Thread.方法名
- 如果想调用动态方法,那么这个线程只能是用第二种方法创建的(extends Thread),否则无法使用Thread类的方法
- isAlive活着的定义是就绪、执行、阻塞状态
- 死了的定义是还没开始、执行完毕
- 线程是有优先级的,优先级高的获得Cpu执行时间长,并不代表优先级低的就得不到执行
- sleep是暂停一会,是静态方法,不需new 出Thread对象就可以执行
- 这个异常是睡眠时 被打断的异常,所以必须写try catch
- 并且sleep方法执行过程中获得当前对象的锁,其他线程无法访问当前资源
- Thread的sleep方法在哪个线程执行哪个线程就会睡眠
- sleep方法适用于几个场合:
1.倒计时,间隔n秒打印一个数字
2.模拟网络延时
———————————————————————— - 方法interrupt可以主动的中断线程,打断之后会抛异常InterruptedException
- 调用Interrupt方法时,线程的中断状态将被置位。这是每一个先后才能都具有的boolean标志
- 每个线程都应该不时检查这个标志,以判断线程是否被中断
如果得到中断状态得到置位?
调用静态的Thread.currentThread.isInterrupted()方法,但是线程处于阻塞状态时无法检测是否中断
当在一个被阻塞的线程(wait sleep)调用interrupt方法,阻塞调用被会InterruptedException异常中断。
一个被中断的线程未必会终止,如何相应中断应该取决于线程是否重要,是否应该不理会异常
如果在每次循环之后都调用sleep或其他的可中断的方法,那么isInterrupted方法是无效的。
如果在中断之后,中断状态被置位,然后调用sleep方法,此时不会睡眠,而是清除中断状态,并抛出中断异常。因此循环调用sleep是没有必要调用isInterrupted方法来判断是否被中断(sleep方法本身会进行判断,如果中断那么抛异常)
interrupted和isInterrupted是两个方法 - 前者是一个静态方法,检测是否被中断,并且清除中断状态;后者是一个非静态方法,只会进行检测。
- 如果在某个方法中调用了sleep方法,应该将InterruptedException异常抛出
- 应该在最终的run方法中来将InterruptedException异常捕捉
这种方法可以使子线程结束,但这种方法不好,太粗暴 - stop方法更加粗暴,不要使用





线程停止方法:

如何让线程自然停止?
run方法结束,线程就结束,可以在run方法中加一个flag和一个可以设置flag为false的关闭方法,当主线程结束想要分支的线程也随之结束的话,可以调用shutDown 方法使run中的循环结束。run方法结束,该分支线程结束。
但是对于阻塞方法的调用,这种停止是无效的
示例1(不温和的停止):
import java.util.*;
public class test {
public static void main(String []args){
MyThread mt = new MyThread();
mt.start();//方法2:start而不是run来启动进程
try{
Thread.sleep(10000);
}catch (InterruptedException e){}
mt.interrupt();
}
}
class MyThread extends Thread {
public void run (){
while(true ){
System.out.println("=="+ new Date() + "=="); //该循环每秒执行一次
try{
sleep(1000);
}catch (InterruptedException e ){
return ;
}
}
}
}输出结果:
Fri Mar 04 19:38:59 CST 2016
Fri Mar 04 19:39:00 CST 2016
Fri Mar 04 19:39:01 CST 2016
示例2(温和的停止):
public class test {
public static void main(String []args){
MyThread thread = new MyThread();
Thread t = new Thread(thread);
t.start();
for(int i = 0; i<1000 ;i++){
if(i %100 == 0 && i != 0)
System.out.println("The main thread:"+ i);
}
System.out.println("The main thread is over");
thread.shutDown(); //代表这主线程执行完毕,程序最后将分支结束
}
}
class MyThread implements Runnable {
boolean flag = true;//可以调用shutdown方法使这个死循环停止
public void run() {
int i = 0;
while(flag){
System.out.println(i++);
}
}
public void shutDown () {
flag = false;
}
}————————————————————————
join 方法:用于合并某个线程
- start线程之后可以join这个线程
- join方法的作用是将分出来的线程合并回去,等待分出来的线程执行完 毕后继续执行原有线程。类似于方法调用。
- join方法也会抛出InterruptedException
Thread类的构造方法1:
Thread类的构造方法2: - new 一个子类对象的同时也new了其父类的对象,只是如果不显式调用父类的构造方法super(),那么会自动调用无参数的父类的构造方法。
可以在自定义类MyThread中(继承自Thread类)中写一个构造方法,显式调用父类的构造方法,其参数为一个字符串,表示创建一个以该字符串为名字的Thread对象。效果是创建了一个MyThread对象,并且其父类Thread对象的名字是给定的字符串。 - 如果不显式调用父类的构造方法super(参数),那么默认父类Thread是没有名字的。
- Thread类有一个动态方法可以返回线程的名称 getName。
在子类对象中调用这个方法,且其父类对象是有名字的,那么返回的是父类Thread的名字
示例:
public class test {
public static void main(String []args){
MyThread thread = new MyThread("mimi");
thread.start();
try{
thread.join();
}catch (InterruptedException e ){}
for(int i = 0; i<= 5;i++) {
System.out.println("I am Main Thread");
}
}
}
class MyThread extends Thread {
MyThread (String name){
super(name);
}
public void run (){
for(int i = 0; i<=5 ;i++){
System.out.println("I am "+ getName());
try{
sleep(1000);
}catch (InterruptedException e){
return ;
}
}
}
}输出结果:
I am mimi
I am mimi
I am mimi
I am mimi
I am mimi
I am mimi
I am Main Thread
I am Main Thread
I am Main Thread
I am Main Thread
I am Main Thread
I am Main Thread————————————————————————
yield 方法:让出Cpu,让一次时间片
示例:
public class test {
public static void main(String []args){
MyThread m1 = new MyThread("mimi");
MyThread m2 = new MyThread("lala");
m1.start();
m2.start();//共有三条分支,三个线程
}
}
class MyThread extends Thread {
MyThread(String name){
super(name);
}
public void run(){
for(int i = 0; i< 100 ;i++){
System.out.println(getName()+":"+i);
if(i %10 == 0){
yield();
}
}
}
}
部分输出结果:
mimi:8
lala:9
mimi:9
lala:10
mimi:10
lala:11
mimi:11
lala:12
mimi:12当一个线程达到10时无论是刚开始还是执行一段时间都会切换到其他线程继续执行
















