Java多线程代码实战 2021.11.03

1.三种方式实现两个线程交替打印1、2.

package com.ddd.common.work.thirdweek;
 
import jdk.nashorn.internal.codegen.CompilerConstants;
 
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
 
/**
 * @program: DddJavaStudy
 * @description: 测试多线程的题目
 * @author: ddd
 * @create: 2021-08-15 18:57
 **/
public class MyThread<V> {
    public static void main(String[] args) {
        //functionOne();
        //functionTwo();
        functionThree();
    }
 
    // 方式1
    public static void functionOne(){
        System.out.println("方式1 start");
        ThreadOne threadA = new ThreadOne(1);
        ThreadOne threadB = new ThreadOne(2);
        threadA.start();
        threadB.start();
        System.out.println("方式1 end");
    }
 
    // 方式2
    public static void functionTwo(){
        System.out.println("方式2 start");
        ThreadTwo threadA = new ThreadTwo(1);
        new Thread(threadA).start();
        ThreadTwo threadB = new ThreadTwo(2);
        new Thread(threadB).start();
        System.out.println("方式2 end");
    }
 
    // 方式3
    public static <V> void functionThree(){
        System.out.println("方式3 start");
        Callable<V> threadA = new ThreadThree<>(1);
        FutureTask<V> futureTaskA = new FutureTask<>(threadA);
        Thread threadATure = new Thread(futureTaskA);
        threadATure.start();
 
        Callable<V> threadB = new ThreadThree<>(2);
        FutureTask<V> futureTaskB = new FutureTask<>(threadB);
        Thread threadBTure = new Thread(futureTaskB);
        threadBTure.start();
        System.out.println("方式3 end");
    }
 
}
 
/**
 * description: 方式1: 继承 Thread的形式
 * @param null
 * @return :
 * @author : duanjianping
 * @since : 2021/8/15 20:05
 */
class ThreadOne extends Thread{
    private int index;
    public ThreadOne(int index){
       this.index = index;
    }
    @Override
    public void run() {
        synchronized (ThreadOne.class){
            for (int i = 0; i < 5; i++) {
                ThreadOne.class.notify();
                System.out.println(index);
                try {
                    ThreadOne.class.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
 
/**
 * description: 方式2: 实现Runnable接口的形式
 * @param null
 * @return :
 * @author : duanjianping
 * @since : 2021/8/15 20:05
 */
class ThreadTwo implements Runnable{
 
    private int index;
    public ThreadTwo(int index){
        this.index = index;
    }
    @Override
    public void run() {
        synchronized (ThreadTwo.class){
            for (int i = 0; i < 5; i++) {
                ThreadTwo.class.notify();
                System.out.println(index);
                try {
                    ThreadTwo.class.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
 
/**
 * description: 方式3: 实现CallAble接口的形式
 * @param null
 * @return :
 * @author : duanjianping
 * @since : 2021/8/15 20:05
 */
class ThreadThree<V> implements Callable<V> {
 
    private int index;
    public ThreadThree(int index){
        this.index = index;
    }
    @Override
    public V call() {
        synchronized (ThreadThree.class){
            for (int i = 0; i < 5; i++) {
                ThreadThree.class.notify();
                System.out.println(index);
                try {
                    ThreadThree.class.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}

2.已知有一个方法run() 和 5个任务task1、task2、......、task5。 多线程实现任务并行执行。 保证run方法返回时5个任务均已执行完毕

public class Demo {
    public void run() {
        ExecutorService exector = Executors.newFixedThreadPool(5);
        int threadNumber = 5;
        final CountDownLatch countDownLatch = new CountDownLatch(threadNumber);
        for (int i = 0; i < threadNumber; i++) {
            final int threadID = i;
            exector.execute(
                    () -> {
                    try {
                    Thread.sleep(2000);
                    System.out.println(String.format("threadID:[%s] finished!!", threadID));
                    } catch (InterruptedException e) {
                    e.printStackTrace();
                    } finally {
                    countDownLatch.countDown();  //这个不管是否异常都需要数量减,否则会被堵塞无法结束
                    }
                    }
                    );
        }
        try {
            countDownLatch.await();//保证之前的所有的线程都执行完成,才会走下面的
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println(countDownLatch.getCount());
        System.out.println("main thread finished!!");
    }
}

3、实现一个生产者消费者队列模型。 一个队列,一个生产者,一个消费者。 队列满则生产者线程阻塞,消费者消费时唤醒,队列空则消费者线程阻塞,非空时唤醒。

package com.ddd.common.work.thirdweek;
 
import org.junit.Test;
import org.springframework.stereotype.Component;
 
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Random;
 
/**
 * @program: DddJavaStudy
 * @description: 生产消费者模型
 * @author: ddd
 * @create: 2021-08-21 14:41
 **/
@Component
public class ProductConsumer {
    /**
     * description: 第3题解答
     * @param
     * @return : void
     * @author : ddd
     * @since : 2021/8/21 14:47
     */
    @Test
    public void doQuestionThree() {
        Queue<Product> queue = new ArrayDeque<>();
 
        for (int i = 0; i < 10; i++) {
            new Thread(new Producer(queue, 10)).start();
            new Thread(new Consumer(queue, 10)).start();
        }
    }
 
    /**
     * description: 生产类
     * @param null
     * @return :
     * @author : ddd
     * @since : 2021/8/21 14:45
     */
    class Producer implements Runnable{
        private Queue<Product> queue;
        private int maxCapacity;
 
        public Producer(Queue queue, int maxCapacity) {
            this.queue = queue;
            this.maxCapacity = maxCapacity;
        }
 
        @Override
        public void run() {
            synchronized (queue) {
 
                while (queue.size() == maxCapacity) { //一定要用 while,而不是 if,下文解释
                    try {
                        System.out.println("生产者" + Thread.currentThread().getName() + "等待中... Queue 已达到最大容量,无法生产");
                        wait();
                        System.out.println("生产者" + Thread.currentThread().getName() + "退出等待");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (queue.size() == 0) { //队列里的产品从无到有,需要通知在等待的消费者
                    queue.notifyAll();
                }
 
                // TODO 待调试
                //try {
                //    Thread.sleep(1000);
                //} catch (InterruptedException e) {
                //    e.printStackTrace();
                //}
 
                Random random = new Random();
                Integer i = random.nextInt();
                queue.offer(new Product("产品"  + i.toString()));
                System.out.println("生产者" + Thread.currentThread().getName() + "生产了产品:" + i.toString());
            }
        }
    }
 
    /**
     * description: 消费类
     * @param null
     * @return :
     * @author : ddd
     * @since : 2021/8/21 14:45
     */
    class Consumer implements Runnable{
        private Queue<Product> queue;
        private int maxCapacity;
 
        public Consumer(Queue queue, int maxCapacity) {
            this.queue = queue;
            this.maxCapacity = maxCapacity;
        }
 
        @Override
        public void run() {
            synchronized (queue) {
 
                while (queue.isEmpty()) {
                    try {
                        System.out.println("消费者" + Thread.currentThread().getName() + "等待中... Queue 已缺货,无法消费");
                        wait();
                        System.out.println("消费者" + Thread.currentThread().getName() + "退出等待");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (queue.size() == maxCapacity) {
                    queue.notifyAll();
                }
 
                // TODO 待调试
                //try {
                //    Thread.sleep(1000);
                //} catch (InterruptedException e) {
                //    e.printStackTrace();
                //}
 
                Product product = queue.poll();
                System.out.println("消费者" + Thread.currentThread().getName() + "消费了:" + product.getName());
            }
        }
    }
 
    /**
     * description: 产品类
     * @param null
     * @return :
     * @author : ddd
     * @since : 2021/8/21 14:44
     */
    class Product  {
        private String name;
 
        public Product(String name) {
            this.name = name;
        }
 
        public String getName() {
            return name;
        }
 
        public void setName(String name) {
            this.name = name;
        }
    }
}

4、多线程实现累加器。

class AnswerFour {
    /** 总的值 */
    int count=0;
 
    /** 要增长的值*/
    int addNum = 0;
 
 
    @Test
    public int add(int addNum){
        this.addNum = addNum;
        //创建1个任务
        MyRunnable myRunnable1 = new MyRunnable();
 
        //创建5个线程
        for(int i=0;i<4;i++){
            new Thread(myRunnable1).start();
        }
    }
 
    @Test
    public int get(){
        return this.count;
    }
 
    //创建一个实现Runnable的类
    class MyRunnable implements Runnable{
        int i;
        public void run() {
            while(true){
                //锁住的是同一对象
                synchronized(this){
                    if( i++ >= addNum ){
                        break;
                    }
                    System.out.println(Thread.currentThread().getName()+":count:"+(++count));
                    //测试时,线程更容易切换
                    Thread.yield();
                }
 
            }
        }
 
    }
 
}

5、定义注解。

      1).分别在源码层存在、字节码时存在、运行时存在,限定注解作用范围分别为type、method、field。

      2).实现注解@Print,功能是在方法调用前后输出注解上的pre和post内容

 @Target({ ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface InitSource {
    public String value() default "";
}
 
 
@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface InitRunTime {
    public String value() default "";
}
 
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.CLASS)
public @interface InitClass {
    public String value() default "";
}
 
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Print {
    String pre() default "start------";
    String post() default "end-------";
}
 
@Aspect
@Component
public class PrintAop {
    /**
     * description: AOP实现 :假设method方法上加了@Pring注解,请分别在方法执行前后输出@Print注解的pre和post中声明的内容
     * @return : java.lang.Object
     * @author : ddd
     * @since : 2021/8/22 11:57
     */
    @Around(value = "@annotation(com.ddd.common.work.thirdweek.aspect.Print) && @annotation(print)")
    public Object invoke(ProceedingJoinPoint pjp, Print print){//假设该方法执行没有参数
        //print pre.
        System.out.println(print.pre());
        Object res = null;
        try {
            res = pjp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        //print post.
        System.out.println(print.post());
        return res;
    }
}

6、编码分别实现任务延迟5s执行、每5秒执行一次。

// schedule(TimerTask task, long delay) 延迟 delay 毫秒 执行
public static void main(String[] args) {
        for (int i = 0; i < 10; ++i) {
            new Timer("timer - " + i).schedule(new TimerTask() {
                @Override
                public void run() {
                    println(Thread.currentThread().getName() + " run ");
                }
            }, 5000);
        }
}
 
 
// schedule(TimerTask task, Date time) 特定时间執行
public static void main(String[] args) {
        for (int i = 0; i < 10; ++i) {
            new Timer("timer - " + i).schedule(new TimerTask() {
                @Override
                public void run() {
                    println(Thread.currentThread().getName() + " run ");
                }
            }, new Date(System.currentTimeMillis() + 5000));
        }
}
 

7、已知一个对象Person,有方法getHeight()和updateHeight(int height)两个方法分别用来实现获取身高和修改身高。编码使其方法线程安全。

public class Person {
 
    int height;
    public synchronized void updateHeight(int n){
        height += n;
    }
 
    public int getHeight(){
        return height;
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值