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