【Java基础】多线程编程

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();
            }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值