Java之多线程之自己理解的代码

参考链接:https://www.bilibili.com/video/BV1T7411m7Ta?

匿名内部类构造线程

package xuexi1;

public class Thread1 {
	
	public static void main(String[] args) {
		//匿名内部类构造线程,继承Thread
		new Thread() {
			@Override
			public void run() {
				for(int i =0 ; i < 5; i++) {
					System.out.println("this is "+Thread.currentThread().getName()+"'s round "+i);
					try {
						Thread.currentThread().sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}.start();
		//匿名内部类构造线程,实现Runnable
		new Thread(new Runnable() {
			@Override
			public void run() {
				for(int i =0 ; i < 5; i++) {
					System.out.println("this is "+Thread.currentThread().getName()+"'s round "+i);
				}
			}
		}).start();
		//输出main线程的信息
		for(int i =0 ; i < 5; i++) {
			System.out.println("this is "+Thread.currentThread().getName()+"'s round "+i);
		}
		
	}
}
result:
this is Thread-0's round 0
this is main's round 0
this is main's round 1
this is main's round 2
this is main's round 3
this is main's round 4
this is Thread-1's round 0
this is Thread-1's round 1
this is Thread-1's round 2
this is Thread-1's round 3
this is Thread-1's round 4
this is Thread-0's round 1
this is Thread-0's round 2
this is Thread-0's round 3
this is Thread-0's round 4

线程同步的三种方法(以售票为例),包括同步代码块、同步方法、锁

package xuexi1;

public class Lock1 implements Runnable{
	//模拟买票系统,实现线程同步安全的三种方法
	int ticket = 100; //初始票
	Object o = new Object(); //随便创建一个Object对象作为锁对象,注意不能在run内部
	//创建,因为需要每个线程公用一个锁对象
	
	@Override
	public void run() {
		//1.利用同步代码块实现
		while(true) {
			synchronized(o) {
			if(ticket>0) {
				//模拟一个出票时间
				try {
					Thread.currentThread().sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				//输出信息,并出票
				System.out.println(Thread.currentThread().getName()+" sold ticket "+ticket--);
			}
		}
      }
	}
}
package xuexi1;

public class Lock2 implements Runnable{
	//模拟买票系统,实现线程同步安全的三种方法
	int ticket = 100; //初始票
	
	//2.利用同步方法来实现
	public synchronized void sell() {
		if(ticket>0) {
			//模拟一个出票时间
			try {
				Thread.currentThread().sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//输出信息,并出票
			System.out.println(Thread.currentThread().getName()+" sold ticket "+ticket--);
		}
	}
	
	@Override
	public void run() {
		while(true) {
			sell();
      }
	}
}
package xuexi1;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Lock3 implements Runnable{
	//模拟买票系统,实现线程同步安全的三种方法
	int ticket = 100; //初始票
	Lock lock = new ReentrantLock();
	//3.利用Lock锁实现
	
	@Override
	public void run() {
		
		while(true) {
			lock.lock();
			if(ticket>0) {
				//模拟一个出票时间
				try {
					Thread.currentThread().sleep(100);
					//输出信息,并出票
					System.out.println(Thread.currentThread().getName()+" sold ticket "+ticket--);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}finally{
					lock.unlock();  //这样的话,无论是否抛出异常,都会释放锁
				}
			}
      }
	}
}

主系统函数:

package xuexi1;

public class TestLock {
	//模拟出票系统
    //构建三个子线程
	public static void main(String[] args) {
//		//test Lock1
//		Lock1 lock1 = new Lock1();
//        new Thread(lock1).start();
//        new Thread(lock1).start();
//        new Thread(lock1).start();
//       //test Lock2
//      Lock2 lock2 = new Lock2();
//        new Thread(lock2).start();
//        new Thread(lock2).start();
//        new Thread(lock2).start();
        //test Lock3
        Lock3 lock3 = new Lock3();
        new Thread(lock3).start();
        new Thread(lock3).start();
        new Thread(lock3).start();
	}
}
result:
Thread-0 sold ticket 100
Thread-0 sold ticket 99
Thread-0 sold ticket 98
Thread-0 sold ticket 97
Thread-0 sold ticket 96
Thread-0 sold ticket 95
Thread-0 sold ticket 94
Thread-1 sold ticket 93
...
Thread-0 sold ticket 5
Thread-1 sold ticket 4
Thread-1 sold ticket 3
Thread-2 sold ticket 2
Thread-2 sold ticket 1

等待唤醒简单案例

package xuexi1;

public class WaitAndNotify {
	//wait() and notify()
	public static void main(String[] args) {
	//首先需要建立一个锁对象,因为wait和notify都应该针对同一个锁对象
	Object lock = new Object();
		//创建wait()线程
		new Thread() {
			@Override
			public void run() {
				//用同步代码块来实现
				synchronized(lock) {
					System.out.println("我要休息了...");
				    try {
						lock.wait(); //加个lock吧
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}  //进入等待状态
				    System.out.println("休息完毕!"); //被唤醒后
				}
			}
		}.start();
		
		//创建唤醒线程
		new Thread() {
			@Override
			public void run() {
				synchronized(lock) {   //注意,两个同步代码块用的是同一个锁对象
					System.out.println("我要叫醒你了哦!");
					lock.notify();   //同样加个lock吧,若有多个就是随机唤醒一个
					//lock.notifyAll();  //若有多个可能的wait()可用这个
				}
			}
		}.start();
		
	}
}
result:
我要休息了...
我要叫醒你了哦!
休息完毕!

利用等待-唤醒机制有效的实现包子铺和客户之间的通信协调

包子类:

package xuexi1;

public class Baozi {
	//担任包子类
	public boolean state = false; //true表示有包子

}

包子铺类:

package xuexi1;

public class BaoziPu extends Thread{
	//担任包子铺线程
	//先把包子引进来
	Baozi baozi;
	//需要一个构造函数把baozi引进来,这样才能与BaoziEat共享同一个Baozi对象
	public BaoziPu(Baozi baozi) {
		this.baozi = baozi;
	}
	@Override
	public void run() {
		while(true) {
			synchronized(baozi) {  //以包子为锁对象
				//若已有包子,等待
			    if(baozi.state) {
			    	try {
						baozi.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
			    }
			    //若被唤醒了,即包子了
			    System.out.println("开始生产包子...");
			    baozi.state = true;
			    //唤醒吃包子的人
			    baozi.notify();
			}
			
		}
	}

}

吃包子的人类:

package xuexi1;

public class BaoziEat extends Thread{
	//担任吃包子的人线程
	Baozi baozi;
	//需要一个构造函数把baozi引进来,这样才能与BaoziEat共享同一个Baozi对象
	public BaoziEat(Baozi baozi) {
		this.baozi = baozi;
	}
	@Override
	public void run() {
		while(true) {  //while循环记得开!!
			synchronized (baozi) {
			//若无包子,则等待
			if(!baozi.state) {
				try {
					System.out.println("等待包子中...");
					baozi.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			//有包子了
			System.out.println("有包子了,开吃!");
			baozi.state = false;
			System.out.println("吃光了,快做");
			baozi.notify();
		}
		}
	}
}

总流程类

package xuexi1;

public class BaoziSystem {
	//担任总系统
	public static void main(String[] args) {
		Baozi baozi = new Baozi();
	    new BaoziPu(baozi).start();
	    new BaoziEat(baozi).start();
	}
}

创建线程池Thread-pool,并提交三个任务

package xuexi1;

public class Task implements Runnable{
	//0.使用Runnable创建一个线程任务
	int taskNumber =0;
	public Task(int x) {
		super();
		taskNumber=x;
	}
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+" task "+taskNumber);
	}
}
package xuexi1;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class ThreadPool {
	//测试线程池
	public static void main(String[] args) {
		//1.生成线程池,建立一个size为10的线程池
		ExecutorService pool = Executors.newFixedThreadPool(10);
		//2.创建三个不同的任务
		Task r1 = new Task(1);
		Task r2 = new Task(2);
		Task r3 = new Task(3);
		//3.提交任务
		Future f1 = pool.submit(r1);
		Future f2 = pool.submit(r2);
		Future f3 = pool.submit(r3);
		//可以不用f1,f2,f3接着,但是这边蛮看看返回结果...
		System.out.println(f1);
		System.out.println(f2);
		System.out.println(f3);
		//4.关掉线程池,但不建议使用。不关的话,程序是一直在执行...
		//pool.shutdown();
	}
}
result:
java.util.concurrent.FutureTask@232204a1
java.util.concurrent.FutureTask@4aa298b7
java.util.concurrent.FutureTask@7d4991ad
pool-1-thread-2 task 2
pool-1-thread-1 task 1
pool-1-thread-3 task 3

lambda函数编程(同时与匿名函数对比)

首先实现三个接口,分别包含一个无参无返回、有参无返回、有参有返回的函数。而后分别用匿名函数和lambda函数来实现。

package xuexi1;

public interface Interface1 {
	public void fun1();  //无参无返回
}
package xuexi1;

public interface Interface2 {
	public void fun1(int x);  //有参无返回
}
package xuexi1;

public interface Interface3 {
	public int fun1(int x);  //有参有返回
}
package xuexi1;

public class LambdaTest {
	
	public static void main(String[] args) {
		//1.1 用匿名函数构造无参无返回
		outerFun1(new Interface1() {
			@Override
			public void fun1() {
			System.out.println("用匿名内部类实现无参无返回");}
		});
		//1.2 用lambda函数构造无参无返回
		outerFun1(() -> {
			System.out.println("用lambda实现无参无返回");
		});
		
		//2.1 用匿名函数构造有参无返回
		outerFun2(new Interface2(){
			@Override
			public void fun1(int x) {
				System.out.println("用匿名内部类实现有参无返回。参数:"+x);
			}
		});
		//2.2 用lambda构造有参无返回
		outerFun2((int x) -> {
			System.out.println("用lambda实现有参无返回。参数:"+x);
		});
		
		//3.1 用匿名函数构造有参有返回
		outerFun3(new Interface3() {
			@Override
			public int fun1(int x) {
				System.out.print("用匿名内部类实现有参无返回。返回值:");
				return x*2;
			}
		});
		//3.2 用lambda构造有参有返回
		outerFun3((int x)->{
			System.out.print("用lambda实现有参无返回。返回值:");
			return x*2;
		});
		
		//lambda略写~~~~
		System.out.println("lambda略写验证--------");
		//1.2 用lambda函数构造无参无返回
		outerFun1(() -> System.out.println("用lambda实现无参无返回"));
		//2.2 用lambda构造有参无返回
		outerFun2((x) -> System.out.println("用lambda实现有参无返回。参数:"+x));
		//3.2 用lambda构造有参有返回
		outerFun3((x)->{
			System.out.print("用lambda实现有参无返回。返回值:");
			return x*2;
		});  //此时不能省略{},因为方法实现体中不止一个语句
	}

	public static void outerFun1(Interface1 x) {
		x.fun1();
	};
	public static void outerFun2(Interface2 x) {
		x.fun1(100);
	};
	public static void outerFun3(Interface3 x) {
		System.out.println(x.fun1(100));
	};

}
result:
用匿名内部类实现无参无返回
用lambda实现无参无返回
用匿名内部类实现有参无返回。参数:100
用lambda实现有参无返回。参数:100
用匿名内部类实现有参无返回。返回值:200
用lambda实现有参无返回。返回值:200
lambda略写验证--------
用lambda实现无参无返回
用lambda实现有参无返回。参数:100
用lambda实现有参无返回。返回值:200
posted on 2020-10-01 14:17  pipony  阅读(173)  评论(0)    收藏  举报