1,守护线程
设置成守护线程后,如果主线程结束,不保证守护线程执行完整结束。
public class Daemon {
public static void main(String[] args) {
Thread thread = new Thread(new DaemonRunner(),"Daemon");
thread.setDaemon(true);
thread.start();
}
static class DaemonRunner implements Runnable{
@Override
public void run() {
try {
SleepUtils.second(10);
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("DaemonThread finally run");
//守护线程不保证执行finally方法快
}
}
}
}
2,Executors
public class Demo {
public static void readMe() {
//FixedThreadPool被称为可重用固定线程数的线程池
//其corePoolSize和maximumPoolSize都被设置为创建其指定参数的nThreads
//由于调用无界工作队列,拒绝策略无效
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
//singleThreadExecutor的corePoolSize和maximumPoolSize都为1,等效Executors.newFixedThreadPool(1);
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
//cachedThreadPool的corePoolSize为0,maximumPoolSize为Integer.MAX_VALUE,采用无容量的SynchronousQueue
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
}
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.submit(new Thread(new CountThread()), "线程1");
cachedThreadPool.submit(new Thread(new CountThread()), "线程2");
SleepUtils.second(3);
System.out.println("------main-------");
cachedThreadPool.shutdown();
}
static class CountThread implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + ": i = " + i);
SleepUtils.second(1);
}
}
}
}
3,Thread.join
public class Demo {
public static void main(String[] args) {
Thread previous = Thread.currentThread();
for (int i = 0; i < 10; i++) {
//每个线程拥有前一个线程的引用,需要等待前一个线程终止,才能从等待中返回
Thread thread = new Thread(new Domino(previous), String.valueOf(i));
thread.start();
previous = thread;
}
SleepUtils.second(5);
System.out.println(Thread.currentThread().getName() + " terminate.");
}
static class Domino implements Runnable {
private Thread thread;
public Domino(Thread thread) {
this.thread = thread;
}
@Override
public void run() {
try {
//只有thread线程终止,才可以从join()返回
thread.join();
SleepUtils.second(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " terminate.");
}
}
}
4,原子类
public class AtomicTest {
private static void readMe() {
/**
* 以AtomicInteger为例,其它七种类型类似
* ***/
//以下操作为原子操作
AtomicInteger atomicInteger = new AtomicInteger(1);
int i = atomicInteger.incrementAndGet();//自增1且返回之前的值
int i1 = atomicInteger.get();//获得当前值
atomicInteger.compareAndSet(0, 1);//符合期望值就设置新值
atomicInteger.lazySet(1);//总会设置新值
/**
* 数组类型
* */
int[] arr = new int[5];
AtomicIntegerArray array = new AtomicIntegerArray(arr);
array.compareAndSet(0, 0, 1);
/**
* 引用类型
* */
Object object = new Object();
AtomicReference<Object> reference = new AtomicReference<>(object);
reference.compareAndSet(object, new Object());
/**
* 字段类型
* */
AtomicIntegerFieldUpdater<User> age = AtomicIntegerFieldUpdater.newUpdater(User.class, "age");
age.compareAndSet(new User(), 0, 2);
}
static class User {
volatile int age;
}
}
5,安全终止线程
public class Demo {
public static void main(String[] args) {
Runner one = new Runner();
Thread countThread = new Thread(one, "CountThread");
countThread.start();
//睡眠1s,main现场对CountThread进行中断,使CountThread能够感知中断而结束
SleepUtils.second(1);
countThread.interrupt();
Runner two = new Runner();
countThread = new Thread(two, "CountThread");
countThread.start();
//睡眠1s,main现场对CountThread进行cancel,使CountThread能够感知on=false而结束
SleepUtils.second(1);
two.cancel();//主线程:volatile可见性
}
static class Runner implements Runnable{
private long i;
private volatile boolean on = true;
@Override
public void run() {
while (on && !Thread.currentThread().isInterrupted()){
i++;
}
System.out.println("count i = " + i);
}
public void cancel(){
on = false;
}
}
}
6,线程-暂停-恢复-停止
public class Demo {
public static void main(String[] args) {
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
Thread runner = new Thread(new Runner(), "Runner");
runner.setDaemon(true);
runner.start();
SleepUtils.second(3);
//暂停runner
runner.suspend();
System.out.println("main suspend runner at "+ format.format(new Date()));
SleepUtils.second(3);
//恢复runner
runner.resume();
System.out.println("main resume runner at "+ format.format(new Date()));
SleepUtils.second(3);
//停止runner
runner.stop();
System.out.println("main stop runner at "+ format.format(new Date()));
SleepUtils.second(3);
}
static class Runner implements Runnable{
@Override
public void run() {
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
while (true){
System.out.println(Thread.currentThread().getName()+"Run at"+ format.format(new Date()));
SleepUtils.second(1);
}
}
}
}
7,线程中断
public class Interrupt {
public static void main(String[] args) {
//sleepThread 不断尝试睡眠
Thread sleepRunner = new Thread(new SleepRunner(), "sleepRunner");
sleepRunner.setDaemon(true);
//busyThread 忙碌
Thread busyRunner = new Thread(new BusyRunner(), "busyRunner");
busyRunner.setDaemon(true);
sleepRunner.start();
busyRunner.start();
//休息5s,让sleep和busy充分运行
SleepUtils.second(5);
sleepRunner.interrupt();
busyRunner.interrupt();
System.out.println("sleepThread interrupt is "+sleepRunner.isInterrupted());
System.out.println("busyThread interrupt is "+busyRunner.isInterrupted());
SleepUtils.second(5);
}
static class SleepRunner implements Runnable {
//在抛出interruptException时,会清除isInterrupt标志
@Override
public void run() {
while (true) {
SleepUtils.second(10);
}
}
}
static class BusyRunner implements Runnable {
@Override
public void run() {
while (true){
}
}
}
}
8,线程通知机制
public class Demo {
private static boolean flag = true;
private static final Object lock = new Object();
public static void main(String[] args) {
Thread waitThread = new Thread(new Wait(), "WaitThread");
Thread notifyThread = new Thread(new Notify(), "NotifyThread");
waitThread.start();
SleepUtils.second(1);
notifyThread.start();
}
static class Wait implements Runnable {
@Override
public void run() {
//加锁
synchronized (lock) {
//当条件不满足时,继续wait,同时释放lock锁
while (flag) {
try {
System.out.println(Thread.currentThread() + "flag is true.wait @" +
new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
//条件满足时,完成工作
System.out.println(Thread.currentThread() + "flag is false.running @" +
new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
}
static class Notify implements Runnable {
@Override
public void run() {
//加锁,拥有lock的Monitor
synchronized (lock) {
//获取lock的锁,然后进行通知,通知时不会释放lock的锁
//直到当前线程释放了lock后,WaitThread才能从wait方法中返回
System.out.println(Thread.currentThread() + "hold lock.notify @" +
new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.notifyAll();
flag = false;
SleepUtils.second(5);
}
//再次加锁(抢占)
synchronized (lock) {
System.out.println(Thread.currentThread() + "hold lock again.sleep @" +
new SimpleDateFormat("HH:mm:ss").format(new Date()));
SleepUtils.second(5);
}
}
}
}
9,输入输出管道
public class Demo {
public static void main(String[] args) throws IOException {
PipedWriter out = new PipedWriter();
PipedReader in = new PipedReader();
//将输入流和输出流进行连接,否则抛出IOException
out.connect(in);
Thread printThread = new Thread(new Print(in), "PrintThread");
printThread.start();
int receive = 0;
try {
while ((receive = System.in.read()) != -1) {
out.write(receive);
}
} finally {
out.close();
}
}
static class Print implements Runnable {
private PipedReader in;
public Print(PipedReader in) {
this.in = in;
}
@Override
public void run() {
int receive = 0;
try {
while ((receive = in.read()) != -1) {
System.out.print((char) receive);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
10,线程间通信
/**
* @program: algorithm_by_java
* @author: 一树
* @data: 2020/12/5 21:46
*
* @Text: 保证多线程中只有一个线程执行同步块,线程a获取锁代表a开始写入消息,线程a释放锁代表a发送消息,
* 线程b获取锁代表b接收a发送的消息,这即是线程间通信。volatile的可见性同样适合线程间通信.
* volatile:保证原子性和可见性,即强制从共享内存区读取数据,避免多线程间脏读
*/
public class Synchronized {
public static void main(String[] args) {
//对Synchronized.class对象加锁
synchronized (Synchronized.class){
}
//静态同步方法,对Synchronized.class对象加锁
m();
}
public static synchronized void m(){}
//对实例加锁
public synchronized void n(){}
}
11,锁
(1)BlockQueue
public class BlockQueue<T> {
private Object[] items;
private Lock lock = new ReentrantLock();
private Condition notEmpty = lock.newCondition();
private Condition notFull = lock.newCondition();
private int addIndex, removeIndex, count;
BlockQueue(int capacity) {
this.items = new Object[capacity];
}
//添加一个元素,如果队列已满,阻塞,直到有空位
public void add(T t) {
lock.lock();
try {
while (count == items.length) {
notFull.await();
}
items[addIndex] = t;
if (++addIndex == items.length) {
addIndex = 0;
}
++count;
notEmpty.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//移除一个元素,如果队列为空,阻塞
@SuppressWarnings("unchecked")
public T remove() {
lock.lock();
try {
while (count == 0) {
notEmpty.await();
}
Object item = items[removeIndex];
if (++removeIndex == items.length) {
removeIndex = 0;
}
--count;
notFull.signal();
return (T) item;
} catch (InterruptedException e) {
e.printStackTrace();
return null;
} finally {
lock.unlock();
}
}
}
(2)Condition
public class Condition {
private static Lock lock = new ReentrantLock();
private static java.util.concurrent.locks.Condition condition = lock.newCondition();
public static void main(String[] args) {
}
private static class CountRunning implements Runnable {
private Lock lock;
private java.util.concurrent.locks.Condition condition;
public CountRunning(Lock lock, java.util.concurrent.locks.Condition condition) {
this.lock = lock;
this.condition = condition;
}
@Override
public void run() {
lock.lock();
try {
condition.await();//condition提供了类似Object的wait notify notifyAll方法
//condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
(3)ReentrantLock简单实现
public class ReentrantLock implements Lock {
private Sync sync = new Sync();
private static class Sync extends AbstractQueuedSynchronizer {
public Sync() {
setState(0);
}
@Override
protected boolean tryAcquire(int arg) {
Thread current = Thread.currentThread();
int state = getState();
if (state == 0) {
if (compareAndSetState(0, arg)) {
setExclusiveOwnerThread(current);
return true;
}
} else if (current == getExclusiveOwnerThread()) {
//可重入,继续判断
int nextState = state + arg;
if (nextState < 0) {
throw new Error("Maximum lock count exceeded");
}
setState(nextState);
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
int c = getState() - arg;
if (Thread.currentThread() != getExclusiveOwnerThread()) {
throw new IllegalMonitorStateException();
}
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
//当可重入为0时,才可释放锁
return free;
}
}
@Override
public void lock() {
sync.acquire(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public void unlock() {
sync.release(1);
}
@Override
public Condition newCondition() {
return null;
}
}
(4)自定义独占锁
public class Mutex implements Lock {
private static class Sync extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int arg) {
//当状态为0时获取锁
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
//释放锁,状态设置为0
if (super.getState() == 0) {
throw new IllegalMonitorStateException();
}
super.setExclusiveOwnerThread(null);
super.setState(0);
return true;
}
@Override
protected boolean isHeldExclusively() {
return super.getState() == 1;
}
//返回一个condition,每个condition都包含了一个condition队列
Condition newCondition() {
return new ConditionObject();
}
}
//仅需要将操作代理到sync上即可
private final Sync sync = new Sync();
@Override
public void lock() {
sync.acquire(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
return sync.tryAcquire(1);
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(time));
}
@Override
public void unlock() {
sync.release(1);
}
@Override
public Condition newCondition() {
return sync.newCondition();
}
public boolean isLocked() {
return sync.isHeldExclusively();
}
public boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
//test
public static void main(String[] args) {
Lock lock = new Mutex();
lock.lock();
try {
System.out.println("lock");
SleepUtils.second(1);
}finally {
lock.unlock();
}
}
}
(5)同步器的理解
/**
* @program: algorithm_by_java
* @author: 一树
* @data: 2020/12/8 22:15
* @Text: 加深对同步器的理解,自定义一个:该工具在同一时刻,只允许至多两个线程访问,超过两个线程将被阻塞
*/
public class TwinsLock implements Lock {
//count 表示可获得同步状态的最大线程数
private static Sync sync = new Sync(2);
private static class Sync extends AbstractQueuedSynchronizer {
Sync(int count) {
if (count <= 0) {
throw new IllegalArgumentException("count must large than zero!!!");
}
setState(count);
}
@Override
protected int tryAcquireShared(int reduceCount) {
while (true) {
int current = getState();
int newCount = current - reduceCount;
if (newCount < 0 || compareAndSetState(current, newCount)) {
return newCount;
}
}
}
@Override
protected boolean tryReleaseShared(int returnCount) {
while (true) {
int current = getState();
int newCount = current + returnCount;
if (compareAndSetState(current, newCount)) {
return true;
}
}
}
}
@Override
public void lock() {
sync.acquireShared(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}
@Override
public void unlock() {
sync.releaseShared(1);
}
@Override
public Condition newCondition() {
return null;
}
//test
public static void main(String[] args) {
Lock lock = new TwinsLock();
Thread thread1 = new Thread(new CountRunning(lock), "countThread-1");
Thread thread2 = new Thread(new CountRunning(lock), "countThread-2");
Thread thread3 = new Thread(new CountRunning(lock), "countThread-3");
Thread thread4 = new Thread(new CountRunning(lock), "countThread-4");
Thread thread5 = new Thread(new CountRunning(lock), "countThread-5");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
}
private static class CountRunning implements Runnable {
private Lock lock;
public CountRunning(Lock lock) {
this.lock = lock;
}
@Override
public void run() {
lock.lock();
try {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + " i = " + i);
SleepUtils.second(1);
}
}finally {
lock.unlock();
}
}
}
}