- 获取当前线程名称
- 状态监测
- 线程优先级设置
- 死锁及解决方法
- 获取线程id
- 线程挂起
- 终止线程
- 生产者/消费者问题
- 获取线程状态
- 获取所有线程
- 查看线程优先级
- 中断线程
public class MyThread extends Thread {
public void run() {
for (int i = 0; i < 5; i++) {
printMsg();
}
}
public void printMsg() {
Thread t = Thread.currentThread();
String name = t.getName();
System.out.println("name=" + name);
}
public static void main(String[] args) {
System.out.println("----------");
MyThread tt = new MyThread();
tt.setName("Thread");
System.out.println("before start(), tt.isAlive()=" + tt.isAlive());
tt.start();
System.out.println("just after start(), tt.isAlive()=" + tt.isAlive());
for (int i = 0; i < 5; i++) {
tt.printMsg();
}
System.out.println("The end of main(), tt.isAlive()=" + tt.isAlive());
System.out.println("----------");
}
}
public class MyThread extends Thread {
boolean waiting = true;
boolean ready = false;
public void run() {
String thrdName = Thread.currentThread().getName();
System.out.println(thrdName + " starting.");
while (waiting)
System.out.println("waiting:" + waiting);
System.out.println("waiting...");
startWait();
try {
Thread.sleep(1000);
} catch (Exception exc) {
System.out.println(thrdName + " interrupted.");
}
System.out.println(thrdName + " terminating.");
}
synchronized void startWait() {
try {
while (!ready)
wait();
} catch (InterruptedException exc) {
System.out.println("wait() interrupted");
}
}
synchronized void notice() {
ready = true;
notify();
}
public static void main(String args[]) throws Exception {
MyThread thrd = new MyThread();
thrd.setName("MyThread #1");
showThreadStatus(thrd);
thrd.start();
Thread.sleep(50);
showThreadStatus(thrd);
System.out.println();
thrd.waiting = false;
Thread.sleep(50);
showThreadStatus(thrd);
thrd.notice();
Thread.sleep(50);
showThreadStatus(thrd);
while (thrd.isAlive())
System.out.println("alive");
showThreadStatus(thrd);
}
static void showThreadStatus(Thread thrd) {
System.out.println(thrd.getName() + "Alive:=" + thrd.isAlive() + " State:=" + thrd.getState());
}
}
public class MyThread extends Thread {
private int countDown = 5;
private volatile double d = 0;
public MyThread(int priority) {
setPriority(priority);
start();
}
public String toString() {
return super.toString() + ": " + countDown;
}
public void run() {
while (true) {
for (int i = 1; i < 100000; i++)
d = d + (Math.PI + Math.E) / (double) i;
System.out.println(this);
if (--countDown == 0)
return;
}
}
public static void main(String[] args) {
new MyThread(Thread.MAX_PRIORITY);
for (int i = 0; i < 5; i++)
new MyThread(Thread.MIN_PRIORITY);
}
}
- 死锁及解决方法
- java 死锁产生的四个必要条件
- 互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
- 不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放
- 请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有
- 循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路
- 当上述四个条件都成立的时候,便形成死锁。如果打破上述任何一个条件,便可让死锁消失
- 解决死锁问题的方法
- 一种是用synchronized
- 一种是用Lock显式锁实现
- 模拟死锁的产生
import java.util.Date;
public class LockTest {
public static String obj1 = "obj1";
public static String obj2 = "obj2";
public static void main(String[] args) {
LockA la = new LockA();
new Thread(la).start();
LockB lb = new LockB();
new Thread(lb).start();
}
}
class LockA implements Runnable {
public void run() {
try {
System.out.println(new Date().toString() + " LockA 开始执行");
while (true) {
synchronized (LockTest.obj1) {
System.out.println(new Date().toString() + " LockA 锁住 obj1");
Thread.sleep(3000);
synchronized (LockTest.obj2) {
System.out.println(new Date().toString() + " LockA 锁住 obj2");
Thread.sleep(60 * 1000);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class LockB implements Runnable {
public void run() {
try {
System.out.println(new Date().toString() + " LockB 开始执行");
while (true) {
synchronized (LockTest.obj2) {
System.out.println(new Date().toString() + " LockB 锁住 obj2");
Thread.sleep(3000);
synchronized (LockTest.obj1) {
System.out.println(new Date().toString() + " LockB 锁住 obj1");
Thread.sleep(60 * 1000);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 此时死锁产生。为了解决它,我们不使用显示的去锁,我们用信号量去控制。信号量可以控制资源能被多少线程访问,这里我们指定只能被一个线程访问,就做到了类似锁住。而信号量可以指定去获取的超时时间,我们可以根据这个超时时间,去做一个额外处理。对于无法成功获取的情况,一般就是重复尝试,或指定尝试的次数,也可以马上退出。
import java.util.Date;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class UnLockTest {
public static String obj1 = "obj1";
public static final Semaphore a1 = new Semaphore(1);
public static String obj2 = "obj2";
public static final Semaphore a2 = new Semaphore(1);
public static void main(String[] args) {
LockAa la = new LockAa();
new Thread(la).start();
LockBb lb = new LockBb();
new Thread(lb).start();
}
}
class LockAa implements Runnable {
public void run() {
try {
System.out.println(new Date().toString() + " LockA 开始执行");
while (true) {
if (UnLockTest.a1.tryAcquire(1, TimeUnit.SECONDS)) {
System.out.println(new Date().toString() + " LockA 锁住 obj1");
if (UnLockTest.a2.tryAcquire(1, TimeUnit.SECONDS)) {
System.out.println(new Date().toString() + " LockA 锁住 obj2");
Thread.sleep(60 * 1000);
} else {
System.out.println(new Date().toString() + "LockA 锁 obj2 失败");
}
} else {
System.out.println(new Date().toString() + "LockA 锁 obj1 失败");
}
UnLockTest.a1.release();
UnLockTest.a2.release();
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class LockBb implements Runnable {
public void run() {
try {
System.out.println(new Date().toString() + " LockB 开始执行");
while (true) {
if (UnLockTest.a2.tryAcquire(1, TimeUnit.SECONDS)) {
System.out.println(new Date().toString() + " LockB 锁住 obj2");
if (UnLockTest.a1.tryAcquire(1, TimeUnit.SECONDS)) {
System.out.println(new Date().toString() + " LockB 锁住 obj1");
Thread.sleep(60 * 1000);
} else {
System.out.println(new Date().toString() + "LockB 锁 obj1 失败");
}
} else {
System.out.println(new Date().toString() + "LockB 锁 obj2 失败");
}
UnLockTest.a1.release();
UnLockTest.a2.release();
Thread.sleep(10 * 1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class MyThread extends Object implements Runnable {
private ThreadID var;
public MyThread(ThreadID v) {
this.var = v;
}
public void run() {
try {
print("var getThreadID =" + var.getThreadID());
Thread.sleep(2000);
print("var getThreadID =" + var.getThreadID());
} catch (InterruptedException x) {
}
}
private static void print(String msg) {
String name = Thread.currentThread().getName();
System.out.println(name + ": " + msg);
}
public static void main(String[] args) {
ThreadID tid = new ThreadID();
MyThread shared = new MyThread(tid);
try {
Thread threadA = new Thread(shared, "threadA");
threadA.start();
Thread.sleep(500);
Thread threadB = new Thread(shared, "threadB");
threadB.start();
Thread.sleep(500);
Thread threadC = new Thread(shared, "threadC");
threadC.start();
} catch (InterruptedException x) {
}
}
}
class ThreadID extends ThreadLocal {
private int nextID;
public ThreadID() {
nextID = 10001;
}
private synchronized Integer getNewID() {
Integer id = new Integer(nextID);
nextID++;
return id;
}
protected Object initialValue() {
print("in initialValue()");
return getNewID();
}
public int getThreadID() {
Integer id = (Integer) get();
return id.intValue();
}
private static void print(String msg) {
String name = Thread.currentThread().getName();
System.out.println(name + ": " + msg);
}
}
public class MyThread extends Thread {
private int countDown = 5;
private static int threadCount = 0;
public MyThread() {
super("" + ++threadCount);
start();
}
public String toString() {
return "#" + getName() + ": " + countDown;
}
public void run() {
while (true) {
System.out.println(this);
if (--countDown == 0)
return;
try {
sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 5; i++)
new MyThread().join();
System.out.println("线程已被挂起");
}
}
- 终止线程
- stop()方法终止线程,但这个方法是不安全的,不建议使用
- 使用interrupt方法来终端线程
- 情况一:线程处于阻塞状态,如使用了sleep方法。使用interrupt方法,sleep方法将抛出一个InterruptedException
- 情况二:使用while(!isInterrupted()){……}来判断线程是否被中断。线程将直接退出
public class MyThread extends Thread {
public void run() {
try {
sleep(10000);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) throws Exception {
Thread thread = new MyThread();
thread.start();
System.out.println("在10秒之内按任意键中断线程!");
System.in.read();
thread.interrupt();
thread.join();
System.out.println("线程已经退出!");
}
}
- 生产者/消费者问题 - 生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,如下图所示,生产者向空间里存放数据,而消费者取用数据,如果不加以协调可能会出现以下情况:存储空间已满,而生产者占用着它,消费者等着生产者让出空间从而去除产品,生产者等着消费者消费产品,从而向空间中添加产品。互相等待,从而发生死锁。
- 通过线程解决生产者/消费者问题
public class ProducerConsumerTest {
public static void main(String[] args) {
CubbyHole c = new CubbyHole();
Producer p1 = new Producer(c, 1);
Consumer c1 = new Consumer(c, 1);
p1.start();
c1.start();
}
}
class CubbyHole {
private int contents;
private boolean available = false;
public synchronized int get() {
while (available == false) {
try {
wait();
} catch (InterruptedException e) {
}
}
available = false;
notifyAll();
return contents;
}
public synchronized void put(int value) {
while (available == true) {
try {
wait();
} catch (InterruptedException e) {
}
}
contents = value;
available = true;
notifyAll();
}
}
class Consumer extends Thread {
private CubbyHole cubbyhole;
private int number;
public Consumer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
}
public void run() {
int value = 0;
for (int i = 0; i < 5; i++) {
value = cubbyhole.get();
System.out.println("消费者 #" + this.number + " got: " + value);
}
}
}
class Producer extends Thread {
private CubbyHole cubbyhole;
private int number;
public Producer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
}
public void run() {
for (int i = 0; i < 5; i++) {
cubbyhole.put(i);
System.out.println("生产者 #" + this.number + " put: " + i);
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
}
}
}
}
- Java中的线程的生命周期大体可分为5种状态
- 新建状态(New):新创建了一个线程对象。
- 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
- 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。yield()方法变成就绪状态。
- 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。notify()/notifyall()或Interrupt()后变成同步阻塞
(二)、同步阻塞:运行的线程在获取对象的同步锁时(synchronized),若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。同步锁被释放后变成就绪状态
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
- 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
- 获取线程状态
public class MyThread extends Thread {
boolean waiting = true;
boolean ready = false;
public void run() {
String thrdName = Thread.currentThread().getName();
System.out.println(thrdName + " 启动");
while (waiting)
System.out.println("等待:" + waiting);
System.out.println("等待...");
startWait();
try {
Thread.sleep(1000);
} catch (Exception exc) {
System.out.println(thrdName + " 中断。");
}
System.out.println(thrdName + " 结束。");
}
synchronized void startWait() {
try {
while (!ready)
wait();
} catch (InterruptedException exc) {
System.out.println("wait() 中断。");
}
}
synchronized void notice() {
ready = true;
notify();
}
public static void main(String args[]) throws Exception {
MyThread thrd = new MyThread();
thrd.setName("MyThread #1");
showThreadStatus(thrd);
thrd.start();
Thread.sleep(50);
showThreadStatus(thrd);
thrd.waiting = false;
Thread.sleep(50);
showThreadStatus(thrd);
thrd.notice();
Thread.sleep(50);
showThreadStatus(thrd);
while (thrd.isAlive()) {
System.out.println("alive");
}
showThreadStatus(thrd);
}
static void showThreadStatus(Thread thrd) {
System.out.println(thrd.getName() + " 存活:" + thrd.isAlive() + " 状态:" + thrd.getState());
}
}
public class MyThread extends Thread {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.setName("thread1");
t1.start();
MyThread t2 = new MyThread();
t2.setName("thread2");
t2.start();
ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
int noThreads = currentGroup.activeCount();
Thread[] lstThreads = new Thread[noThreads];
currentGroup.enumerate(lstThreads);
for (int i = 0; i < noThreads; i++)
System.out.println("线程号:" + i + " = " + lstThreads[i].getName());
}
}
public class MyThread extends Object {
private static Runnable makeRunnable() {
Runnable r = new Runnable() {
public void run() {
for (int i = 0; i < 5; i++) {
Thread t = Thread.currentThread();
System.out.println("in run() - priority=" + t.getPriority() + ", name=" + t.getName());
try {
Thread.sleep(2000);
} catch (InterruptedException x) {
}
}
}
};
return r;
}
public static void main(String[] args) {
System.out.println("in main() - Thread.currentThread().getPriority()=" + Thread.currentThread().getPriority());
System.out.println("in main() - Thread.currentThread().getName()=" + Thread.currentThread().getName());
Thread threadA = new Thread(makeRunnable(), "threadA");
threadA.start();
try {
Thread.sleep(2000);
} catch (InterruptedException x) {
}
System.out.println("in main() - threadA.getPriority()=" + threadA.getPriority());
}
}
public class MyThread extends Object implements Runnable {
public void run() {
try {
System.out.println("in run() - 将运行 work2() 方法");
work2();
System.out.println("in run() - 从 work2() 方法回来");
} catch (InterruptedException x) {
System.out.println("in run() - 中断 work2() 方法");
return;
}
System.out.println("in run() - 休眠后执行");
System.out.println("in run() - 正常离开");
}
public void work2() throws InterruptedException {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("C isInterrupted()=" + Thread.currentThread().isInterrupted());
Thread.sleep(2000);
System.out.println("D isInterrupted()=" + Thread.currentThread().isInterrupted());
}
}
}
public void work() throws InterruptedException {
while (true) {
for (int i = 0; i < 100000; i++) {
int j = i * 2;
}
System.out.println("A isInterrupted()=" + Thread.currentThread().isInterrupted());
if (Thread.interrupted()) {
System.out.println("B isInterrupted()=" + Thread.currentThread().isInterrupted());
throw new InterruptedException();
}
}
}
public static void main(String[] args) {
MyThread si = new MyThread();
Thread t = new Thread(si);
t.start();
try {
Thread.sleep(2000);
} catch (InterruptedException x) {
}
System.out.println("in main() - 中断其他线程");
t.interrupt();
System.out.println("in main() - 离开");
}
}