三个线程依次执行
思路一:使用join, join底层使用wait使得当前线程终止,c++去唤醒
public class ThreadJoin {
private static class Thread1 extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+ "----------------");
}
}
private static class Thread2 extends Thread {
private Thread1 thread1;
private Thread2(Thread1 thread1) {
this.thread1 = thread1;
}
@Override
public void run() {
try {
this.thread1.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName()+ "----------------");
}
}
private static class Thread3 extends Thread {
private Thread2 thread2;
private Thread3(Thread2 thread2){
this.thread2 = thread2;
}
@Override
public void run() {
try {
this.thread2.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName()+ "----------------");
}
}
public static void main(String[] args) {
Thread1 thread1 = new Thread1();
thread1.setName("线程一");
thread1.start();
Thread2 thread2 = new Thread2(thread1);
thread2.setName("线程二");
thread2.start();
Thread3 thread3 = new Thread3(thread2);
thread3.setName("线程三");
thread3.start();
}
}
思路二:使用一个变量 三个值一次唤醒
public class ThreadJoin {
private static int status = 0;
private static Object lock = new Object();
private static class Thread1 extends Thread {
@Override
public void run() {
synchronized (lock) {
while (status != 0) {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(Thread.currentThread().getName()+ "----------------");
status = 1;
lock.notify();
}
}
}
private static class Thread2 extends Thread {
@Override
public void run() {
synchronized (lock) {
while (status != 1) {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(Thread.currentThread().getName()+ "----------------");
status = 2;
lock.notify();
}
}
}
private static class Thread3 extends Thread {
@Override
public void run() {
synchronized (lock) {
while (status != 2) {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName()+ "----------------");
}
}
}
}
public static void main(String[] args) {
Thread1 thread1 = new Thread1();
thread1.setName("线程一");
thread1.start();
Thread2 thread2 = new Thread2();
thread2.setName("线程二");
thread2.start();
Thread3 thread3 = new Thread3();
thread3.setName("线程三");
thread3.start();
}
}
二、线程状态
1、新建状态 (新建thread)
2、就绪状态(调用start)
3、运行状态 (执行run内的方法)
4、终止状态 (run方法内执行结束)
5、阻塞状态(synchroized 、调用wait,join, 唤醒调用notify让线程处于就绪状态)
6、等待超时状态(wait(100))
7、等待状态 (wait)
三、线程种类
1、守护线程:依赖用户线程,用户线程退出了,守护线程也退出,例如垃圾回收线程(调用Thread setDaemon(true))
2、用户线程:独立存在的,不会因为其他用户线程退出而退出
public class ThreadDeamon {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println("子线程正在运行");
try {
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});
thread.setDaemon(true);
thread.start();
System.out.println("主线程结束");
}
}
四、线程终止
1、使用interrupt()方法,wait\sleep\join会抛异常
2、使用标志位
public class ThreadFinish {
public static class Thread1 extends Thread {
private volatile boolean isRun = true;
@Override
public void run() {
while (isRun) {
try {
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//线程终止前可以做的操作
System.out.println("线程终止了");
}
public void startThread() {
isRun = true;
this.start();
}
public void stopThread() {
isRun = false;
this.interrupt();
}
}
public static void main(String[] args) {
Thread1 thread1 = new Thread1();
thread1.startThread();
try {
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
thread1.stopThread();
}
}
五、ReentrantLock、Condition使用 两个线程依次打印
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockDemo {
private ReentrantLock reentrantLock = new ReentrantLock();
private Condition condition = reentrantLock.newCondition();
private int status = 1;
private void method1() {
new Thread(new Runnable() {
@Override
public void run() {
try {
reentrantLock.lock();
while (true) {
while (status != 1) {
condition.await();
}
System.out.println(Thread.currentThread().getName());
Thread.sleep(1 * 1000);
status = 2;
condition.signal();
}
} catch (Exception e) {
} finally {
reentrantLock.unlock();
}
}
}, "线程一").start();
}
private void method2() {
new Thread(new Runnable() {
@Override
public void run() {
try {
reentrantLock.lock();
while (true) {
while (status != 2) {
condition.await();
}
System.out.println(Thread.currentThread().getName());
Thread.sleep(1 * 1000);
status = 1;
condition.signal();
}
}catch (Exception e) {
} finally {
reentrantLock.unlock();
}
}
}, "线程二").start();
}
public static void main(String[] args) {
ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
reentrantLockDemo.method1();
reentrantLockDemo.method2();
}
}
六、sleep() wait区别
sleep:不释放线程锁,是Thread内方法
wait:释放线程锁,必须放在synchronized中 是object类方法
七、FutureTask Callable 使用
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class FutureTaskDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("执行开始");
Thread.sleep(1 * 1000);
System.out.println("执行结束");
return 1;
}
};
FutureTask<Integer> futureTask = new FutureTask<>(callable);
new Thread(futureTask).start();
//阻塞等待结果
Integer result = futureTask.get();
System.out.println("执行结果:" + result);
}
}
八、通过wait notify实现FutureTask Callable
public interface MyCallable<V> {
V call() throws Exception;
}
public class MyFutureTask<V> implements Runnable{
private MyCallable<V> myCallable;
private Object lock = new Object();
private V result;
public MyFutureTask(MyCallable<V> myCallable) {
this.myCallable = myCallable;
}
@Override
public void run() {
try {
result = myCallable.call();
synchronized (lock) {
lock.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public V get() {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return result;
}
}
public class MyFutureTaskDemo {
public static void main(String[] args) {
MyCallable<Integer> myCallable = new MyCallable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("线程执行开始");
Thread.sleep(1 * 1000);
System.out.println("线程执行结束");
return 1;
}
};
MyFutureTask<Integer> myFutureTask = new MyFutureTask<>(myCallable);
new Thread(myFutureTask).start();
Integer result = myFutureTask.get();
System.out.println("执行结果:" + result);
}
}
九、HashTable、HashMap区别
1、HashTable:线程安全,通过synchroized保证 不允许Key null
2、HashMap:线程不安全,允许key null
十、ConcurrentHashMap简单实现:
1.7版本:底层使用分段锁设计,将一个大的HashTable线程安全的集合拆分成n多个小的HashTable集合,默认初始化16个小的HashTable集合,如果同时16个线程最终计算index值落在不同的小的HashTable集合,就不会发生锁的竞争,同时可以支持16个线程访问写的操作,效率非常高
import java.util.Hashtable;
public class MyConcurrentHashMap<K, V> {
private final int DEFAULT_LENGT = 16;
private Hashtable<K, V>[] hashtables;
MyConcurrentHashMap(){
hashtables = new Hashtable[DEFAULT_LENGT];
for (int i = 0; i < hashtables.length; i++){
hashtables[i] = new Hashtable<>();
}
}
public void put(K k, V v) {
int index = k.hashCode() % hashtables.length;
hashtables[index].put(k, v);
}
public V get(K k) {
int index = k.hashCode() % hashtables.length;
return hashtables[index].get(k);
}
public static void main(String[] args) {
MyConcurrentHashMap<String, String> hashMap = new MyConcurrentHashMap<>();
hashMap.put("name", "xiaoming");
hashMap.put("age", "12");
System.out.println(hashMap.get("name"));
}
}
网友评论