目录
4.3、interrupt,isInterrupted,interrupted
1、线程状态
public enum State {
start之前
NEW,
可运行线程的线程状态。处于可运行状态的线程正在Java虚拟机中执行,
但它可能正在等待来自操作系统(如处理器)的其他资源。
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
1.1、Blocked
public class MainTest {
public static void main(String[] args) throws InterruptedException {
class Counter {
int counter;
public synchronized void increase() {
counter++;
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
Counter c = new Counter();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
c.increase();
}
}, "t1线程");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
c.increase();
}
}, "t2线程");
t2.start();
Thread.sleep(100); // 确保 t2 run已经得到执行
System.out.println(t2.getState());
}
}
BLOCKED
1.2、Time_waited/Waiting
public class DemoThread extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " run " + Thread.currentThread().getState());
super.run();
try {
Thread.sleep(3000);
waitEx(); waiting状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public synchronized void start() {
System.out.println(Thread.currentThread().getName() + " start " + Thread.currentThread().getState());
super.start();
}
@Override
public State getState() {
return super.getState();
}
public synchronized void waitEx() throws InterruptedException {
wait();
System.out.println(Thread.currentThread().getName() + " waitEx " + Thread.currentThread().getState());
}
public synchronized void notifyEx() {
notify();
System.out.println(Thread.currentThread().getName() + " notifyEx " + Thread.currentThread().getState());
}
}
public class MainTest {
public static void main(String[] args) throws InterruptedException {
DemoThread demoThread = new DemoThread();
System.out.println(demoThread.getState());
demoThread.start();
Thread.sleep(100);
System.out.println(demoThread.getState());
demoThread.notifyEx();
System.out.println(demoThread.getState());
}
}
NEW
main start RUNNABLE
Thread-0 run RUNNABLE
WAITING
main notifyEx RUNNABLE
Thread-0 waitEx RUNNABLE
TERMINATED
2、主线程和子线程
2.1、start和run
- 首先new Thread()出来的对象会分配一个线程名称
- start:来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码;通过调用Thread类的start()方法来启动一个线程, 这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行操作的, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。然后CPU再调度其它线程。
- run:相当于普通方法调用。程序还是会顺序执行,要等待run方法体执行完毕后,才可继续执行下面的代码; 程序中只有主线程——这一个线程, 其程序执行路径还是只有一条, 这样就没有达到写线程的目的。
public static void main(String[] args) throws InterruptedException {
new Thread(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}.start();
}
结果:
Thread-0
public static void main(String[] args) throws InterruptedException {
new Thread(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}.run();
}
结果:
main
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
thread.run();
System.out.println(thread.getName());
}
结果:
main
Thread-0
2.2、主线程结束后不影响子线程
public class SubThread implements Runnable {
@Override
public void run() {
try {
System.out.println("子线程启动");
Thread.sleep(5000);
System.out.println("子线程结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("主线程启动");
Thread thread = new Thread(new SubThread());
thread.start();
Thread.sleep(100);
System.out.println("主线程结束");
}
结果:
主线程启动
子线程启动
主线程结束
子线程结束
2.3、主线程等待子线程结束后结束
public class SubThread implements Runnable {
@Override
public void run() {
try {
System.out.println("子线程启动");
Thread.sleep(1000);
System.out.println("子线程结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class TestMain {
public static void main(String[] args) throws InterruptedException {
System.out.println("主线程启动");
Thread thread = new Thread(new SubThread());
thread.start();
thread.join();
Thread.sleep(100);
System.out.println("主线程结束");
}
}
结果:
主线程启动
子线程启动
子线程结束
主线程结束
2.4、主线程结束后子线程(守护线程)立即终止
子线程需要设置守护线程
public class SubThread implements Runnable {
@Override
public void run() {
try {
System.out.println("子线程启动");
Thread.sleep(1000);
System.out.println("子线程结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class MainTest {
public static void main(String[] args) throws InterruptedException {
System.out.println("主线程启动");
Thread thread = new Thread(new SubThread());
thread.setDaemon(true);
thread.start();
Thread.sleep(100);
System.out.println("主线程结束");
}
}
结果:
主线程启动
子线程启动
主线程结束
2.5、守护线程
用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守护线程的保姆:
只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器),它就是一个很称职的守护者。
User和Daemon两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果 User Thread已经全部退出运行了,只剩下Daemon Thread存在了,虚拟机也就退出了。 因为没有了被守护者,Daemon也就没有工作可做了,也就没有继续运行程序的必要了。
3、sleep和wait
3.1、sleep
sleep()方法是线程类(Thread)的静态方法,使得当前线程进入阻塞状态,给执行机会给其他线程(实际上,调用sleep()方法时并不要求持有任何锁,即sleep()可在任何地方使用。),但是监控状态依然保持,到时后会自动恢复。
当线程处于上锁时,sleep()方法不会释放对象锁,只会让出CPU执行时间片。休眠时间满后,该线程不一定会立即执行,等待CPU调度。
3.2、wait
wait()方法是Object类里的方法,当一个线程执行wait()方法时,它就进入到一个和该对象相关的等待池中(进入等待队列,也就是阻塞的一种,叫等待阻塞),同时释放对象锁,并让出CPU资源,待指定时间结束后返还得到对象锁。
wait()使用notify()方法、notiftAll()方法唤醒当前等待池中的线程。等待的线程只是被激活,但是必须得再次获得锁才能继续往下执行。wait()方法、notify()方法和notiftAll()方法用于协调多线程对共享数据的存取,所以只能在同步方法或者同步块中使用,否则抛出IllegalMonitorStateException。
4、线程相关方法
4.1、join
调用isAlive()判断形成是否活跃,活跃则调用wait()方法等待,活跃是native方法(子线程都在运行则活跃)
public final synchronized void join(long millis) throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
public final native boolean isAlive();
4.2、yield
让出同优先级线程的CPU时间片
public static native void yield();
4.3、interrupt,isInterrupted,interrupted
- interrupt():在一个线程中调用另一个线程的interrupt()方法,即会向那个线程发出信号——线程中断状态已被设置。至于那个线程何去何从,由具体的代码实现决定
- isInterrupted():用来判断当前线程的中断状态(true or false)
- interrupted():是个Thread的static方法,用来恢复中断状态
public class MethodThread extends Thread {
@Override
public void run() {
super.run();
try {
long start = System.currentTimeMillis();
int i = 0;
for (; i < 1000000; i++) {
String str0 = "0";
String str1 = "1";
String str2 = "2";
String str3 = "3";
String str4 = "4";
String str5 = "5";
String str6 = "6";
String str7 = "7";
String str8 = "8";
String str9 = "9";
if (Thread.currentThread().isInterrupted()) {
System.out.println("interrupt");
Thread.interrupted();
System.out.println(Thread.currentThread().isInterrupted());
}
}
System.out.println((System.currentTimeMillis()-start)+" end " + i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class MainTest{
public static void main(String[] args) throws InterruptedException {
MethodThread methodThread = new MethodThread();
methodThread.start();
Thread.sleep(1);
System.out.println(methodThread.isInterrupted());
methodThread.interrupt();
}
}
结果:
false
interrupt
false
16 end 1000000
4.4、stop
方法已废除
- 即刻停止run()方法中剩余的全部工作,包括在catch或finally语句中,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭
- 会立即释放该线程所持有的所有的锁,导致数据得不到同步的处理,出现数据不一致的问题
4.5、suspend/resume
方法已废除
suspend()和resume()必须要成对出现,否则非常容易发生死锁。
因为suspend方法并不会释放锁,如果使用suspend的目标线程对一个重要的系统资源持有锁,那么没任何线程可以使用这个资源直到要suspend的目标线程被resumed,如果一个线程在resume目标线程之前尝试持有这个重要的系统资源锁再去resume目标线程,这两条线程就相互死锁了,也就冻结线程。
public class Main{
public static void main(String [] args) throws Exception{
TestObject testObject = new TestObject();
Thread t1 = new Thread(){
public void run(){
testObject.print();
}
};
t1.setName("A");
t1.start();
Thread.sleep(1000);
Thread t2 = new Thread(){
public void run(){
System.out.println("B已启动,但进入不到print方法中");
testObject.print();
}
};
t2.setName("B");
t2.start();
}
}
class TestObject{
public synchronized void print(){
if(Thread.currentThread().getName().equals("A")){
System.out.println("A 线程 独占该资源了");
Thread.currentThread().suspend();
}
}
}
结果:
A 线程 独占该资源了
已启动,但进入不到print方法中
5、volatile
volatile让变量每次在使用的时候,都从主存中取。而不是从各个线程的“工作内存”。
volatile具有synchronized关键字的“可见性”,但是没有synchronized关键字的“并发正确性”,就是说不保证线程执行的有序性。
volatile变量对于每次使用,线程都能得到当前volatile变量的最新值。