线程是轻量级进程,是程序执行的最小单位;
线程的生命周期:
线程基本操作:
1、新建线程
Thread t = new Thread();
t.start();
Thread的run()方法只会在当前线程中串行执行run()方法中的代码,正确开启新线程应使用start()方法;
public class CreateThread implements Runnable {
@Override
public void run() {
System.out.println("CreateThread.run()");
}
public static void main(String[] args) {
Thread t = new Thread(new CreateThread());
t.start();
}
}
默认的Thread.run()方法就是直接调用内部Runnable接口;
/* What will be run. */
private Runnable target;
/**
* If this thread was constructed using a separate
* <code>Runnable</code> run object, then that
* <code>Runnable</code> object's <code>run</code> method is called;
* otherwise, this method does nothing and returns.
* <p>
* Subclasses of <code>Thread</code> should override this method.
*
* @see #start()
* @see #stop()
* @see #Thread(ThreadGroup, Runnable, String)
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
2、终止线程
stop()方法之所以被废弃,是因为stop()方法过于暴力,强行把正在执行的线程终止,可能会引起一些数据不一致的问题;
不安全的停止线程demo:
public class StopThreadUnsafe {
private static User u = new User();
public static class User {
private int id;
private String name;
public User() {
id = 0;
name = "0";
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
public static class ChangeObjectThread extends Thread {
@Override
public void run() {
while (true) {
synchronized (u) {
int v = (int) (System.currentTimeMillis() / 1000);
u.setId(v);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
u.setName(String.valueOf(v));
}
Thread.yield();
}
}
}
public static class ReadObjectThread extends Thread {
@Override
public void run() {
while (true) {
synchronized (u) {
if (u.getId() != Integer.parseInt(u.getName())) {
System.out.println(u);
}
}
Thread.yield();
}
}
}
@SuppressWarnings("deprecation")
public static void main(String[] args) throws InterruptedException {
new ReadObjectThread().start();
while (true) {
Thread t = new ChangeObjectThread();
t.start();
Thread.sleep(150);
t.stop();
}
}
}
##################################################
console
User [id=1549372735, name=1549372734]
User [id=1549372735, name=1549372734]
User [id=1549372735, name=1549372734]
User [id=1549372736, name=1549372735]
正确停止线程demo:
public class StopThreadSafe {
private static User u = new User();
public static class User {
private int id;
private String name;
public User() {
id = 0;
name = "0";
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
public static class ChangeObjectThread extends Thread {
private volatile boolean stopme = false;
public void stopMe() {
stopme = true;
}
@Override
public void run() {
while (true) {
if (stopme) {
System.out.println("exit by stop me");
break;
}
synchronized (u) {
int v = (int) (System.currentTimeMillis() / 1000);
u.setId(v);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
u.setName(String.valueOf(v));
}
Thread.yield();
}
}
}
public static class ReadObjectThread extends Thread {
@Override
public void run() {
while (true) {
synchronized (u) {
if (u.getId() != Integer.parseInt(u.getName())) {
System.out.println(u);
}
}
Thread.yield();
}
}
}
public static void main(String[] args) throws InterruptedException {
new ReadObjectThread().start();
while (true) {
ChangeObjectThread t = new ChangeObjectThread();
t.start();
Thread.sleep(150);
t.stopMe();
}
}
}
#####################
console
exit by stop me
exit by stop me
exit by stop me
3、线程中断
线程中断是一种重要的线程协作机制;
public void interrupt() // 中断线程
public boolean isInterrupted() // 判断是否被中断
public static boolean interrupted() // 判断是否被中断,并清除当前中断状态
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
public boolean isInterrupted() {
return isInterrupted(false);
}
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
/**
* Tests if some Thread has been interrupted. The interrupted state
* is reset or not based on the value of ClearInterrupted that is
* passed.
*/
private native boolean isInterrupted(boolean ClearInterrupted);
使用Thread.currentThread().isInterrupted()判断当前线程是否被中断,如果被中断了,退出循环体,结束线程;
public class InterruptThread {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread("interrupt") {
@Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("Interrupted!");
break;
}
}
Thread.yield();
}
};
t.start();
TimeUnit.SECONDS.sleep(2);
t.interrupt();
}
}
Thread.sleep()函数签名:
/**
* Causes the currently executing thread to sleep (temporarily cease
* execution) for the specified number of milliseconds, subject to
* the precision and accuracy of system timers and schedulers. The thread
* does not lose ownership of any monitors.
*
* @param millis
* the length of time to sleep in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
public static native void sleep(long millis) throws InterruptedException;
当线程在休眠被中断时会抛出InterruptedException异常,并清除中断标记,catch捕获后没有选择立即退出线程,而是设置中断标志,保证数据的一致性和完整性;
public class InterruptSleepThread {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread("interrupt-sleep") {
@Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("Interrupted!");
break;
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("Interrupted when sleep.");
// 设置中断状态
Thread.currentThread().interrupt();
}
}
Thread.yield();
}
};
t.start();
Thread.sleep(1500);
t.interrupt();
}
}
4、等待wait()和通知notify()
public final native void wait(long timeout) throws InterruptedException
public final native void notify()
public final native void notifyAll()
Object.wait()方法和Thread.sleep()方法都让线程等待若干时间,wait()方法可以被唤醒,并且wait()方法会释放目标对象的锁,但sleep()方法不会释放任何资源;
public class WaitNotifyDemo {
private static final Object lock = new Object();
public static class WaitThread extends Thread {
@Override
public void run() {
synchronized (lock) {
System.out.println(System.currentTimeMillis() + ":WaitThread start!");
try {
System.out.println(System.currentTimeMillis() + ":WaitThread wait for lock.");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() + ":WaitThread end!");
}
}
}
public static class NotifyThread extends Thread {
@Override
public void run() {
synchronized (lock) {
System.out.println(System.currentTimeMillis() + ":NotifyThread start!");
lock.notify();
System.out.println(System.currentTimeMillis() + ":NotifyThread end!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Thread waitThread = new WaitThread();
Thread notifyThread = new NotifyThread();
waitThread.start();
notifyThread.start();
}
}
1549382736972:WaitThread start!
1549382736972:WaitThread wait for lock.
1549382736972:NotifyThread start!
1549382736972:NotifyThread end!
1549382738977:WaitThread end!
5、挂起suspend()和继续执行resume()线程
/**
* Suspends this thread.
* <p>
* First, the <code>checkAccess</code> method of this thread is called
* with no arguments. This may result in throwing a
* <code>SecurityException </code>(in the current thread).
* <p>
* If the thread is alive, it is suspended and makes no further
* progress unless and until it is resumed.
*
* @exception SecurityException if the current thread cannot modify
* this thread.
* @see #checkAccess
* @deprecated This method has been deprecated, as it is
* inherently deadlock-prone. If the target thread holds a lock on the
* monitor protecting a critical system resource when it is suspended, no
* thread can access this resource until the target thread is resumed. If
* the thread that would resume the target thread attempts to lock this
* monitor prior to calling <code>resume</code>, deadlock results. Such
* deadlocks typically manifest themselves as "frozen" processes.
* For more information, see
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
*/
@Deprecated
public final void suspend() {
checkAccess();
suspend0();
}
/**
* Resumes a suspended thread.
* <p>
* First, the <code>checkAccess</code> method of this thread is called
* with no arguments. This may result in throwing a
* <code>SecurityException</code> (in the current thread).
* <p>
* If the thread is alive but suspended, it is resumed and is
* permitted to make progress in its execution.
*
* @exception SecurityException if the current thread cannot modify this
* thread.
* @see #checkAccess
* @see #suspend()
* @deprecated This method exists solely for use with {@link #suspend},
* which has been deprecated because it is deadlock-prone.
* For more information, see
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
*/
@Deprecated
public final void resume() {
checkAccess();
resume0();
}
suspend()方法挂起线程时导致线程暂停,但不会释放任何锁资源;如果resume()方法意外地在suspend()方法前就执行了,会导致被挂起的线程可能很难有机会被继续执行;并且对于被挂起的线程,从线程状态上看居然还是Runnable;
public class SuspendResumeDemo {
public static Object lock = new Object();
private static ChangeObjectThread t1 = new ChangeObjectThread("t1");
private static ChangeObjectThread t2 = new ChangeObjectThread("t2");
public static class ChangeObjectThread extends Thread {
public ChangeObjectThread(String name) {
super.setName(name);
}
@SuppressWarnings("deprecation")
@Override
public void run() {
synchronized (lock) {
System.out.println("In " + getName());
Thread.currentThread().suspend();
}
}
}
@SuppressWarnings("deprecation")
public static void main(String[] args) throws InterruptedException {
t1.start();
Thread.sleep(100);
t2.start();
t1.resume();
t2.resume();
t1.join();
t2.join();
}
}
In t1
In t2
(t1启动后,持有lock锁,而且suspend()方法不会释放资源,一直持有锁,当t2启动后,无法获得lock锁,t2阻塞;当t1.resume()执行后,t1继续执行,释放lock锁,此时t2获得lock锁,打印In t2,之后t2挂起;与此同时main线程中执行了t2.resume(),这个resume方法没有生效,造成t2永远挂起,并且永远占有lock锁;)
示例代码中,t2线程的resume()方法就在其suspend()方法前执行了,导致t2线程被挂起,程序不会退出,永远被挂起,并且永远占用lock对象的锁;
使用wait()方法和notify()方法模拟挂起和继续执行功能:
public class WaitNotifySimulateSuspendResumeDemo {
public static Object lock = new Object();
public static class ChangeObjectThread extends Thread {
private volatile boolean suspendme = false;
public void suspendMe() {
suspendme = true;
}
public void resumeMe() {
suspendme = false;
synchronized (this) {
notify();
}
}
@Override
public void run() {
while (true) {
synchronized (this) {
while (suspendme) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized (lock) {
System.out.println("In ChangeObjectThread");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Thread.yield();
}
}
}
public static class ReadObjectThread extends Thread {
@Override
public void run() {
while (true) {
synchronized (lock) {
System.out.println("In ReadObjectThread");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Thread.yield();
}
}
}
public static void main(String[] args) throws InterruptedException {
ChangeObjectThread t1 = new ChangeObjectThread();
ReadObjectThread t2 = new ReadObjectThread();
t1.start();
t2.start();
Thread.sleep(1000);
t1.suspendMe();
System.out.println("suspend t1 2 seconds.");
Thread.sleep(2000);
System.out.println("resume t1");
t1.resumeMe();
t1.join();
t2.join();
}
}
6、等待线程结束join()和谦让yeild()
public final void join() throws InterruptedException
public final synchronized void join(long millis) throws InterruptedException
public class JoinDemo {
public volatile static int i = 0;
public static class IncrementThread extends Thread {
@Override
public void run() {
for (i = 0; i < 10000000; i++)
;
}
}
public static void main(String[] args) throws InterruptedException {
IncrementThread it = new IncrementThread();
it.start();
it.join();
System.out.println(i);
}
}
输出i的值为10000000,即it.join()保证了main线程等待IncrementThread执行完毕了之后,再输出i的值;
public static native void yield();
yield()方法会让出CPU,还会进行CPU资源的争夺,但是是否能够再次被分配时间片就不一定了;