JAVA基础32——多线程(2)

1.单例设计模式

  • 单例设计模式:保证类在内存中只有一个对象
    饿汉式和懒汉式的区别:
    1.饿汉式是空间换时间,懒汉式是时间换空间
    2.饿汉式在多线程的使用过程中不会创建多个对象,懒汉式在多线程的使用中可能会创建多个对象
public class DemoSingleton {

	/**
	 * @param args
	 
	 */
	public static void main(String[] args) {
		SingleTon s1 = SingleTon.s;
		SingleTon s2 = SingleTon.s;
		System.out.println(s1==s2);      //true
	}

}
/*
// 饿汉式单例模式(开发时候用)
 
class SingleTon{
	//1.私有构造函数,使得其他的类无法创建对象
	private SingleTon(){
		
	}
	//2.创建本类对象
	private static SingleTon s = new SingleTon();
	//3.对外提供公共的访问方法
	public static SingleTon getInstance(){             //获取实例
		return s;
	}
}
*/

/*
//懒汉式单例模式(面试时候用),单例的延迟加载模式
class SingleTon{
	//1私有构造方法
	private SingleTon(){}
	//2.声明一个对象引用
	private static SingleTon s;
	//对外提供公共的访问方法
	public static SingleTon getInstance() {
		if(s==null){                 //可能会造成多线程创建了多个实例
			s = new SingleTon();
		}
		return s;
	}
}*/
//第三种写法

class SingleTon{
	//1.私有构造方法
	private SingleTon(){}
	//2.创建一个对象
	public static final SingleTon s = new SingleTon();
}
public class DemoTimer {

	/**
	 * @param args
1. public class Timer extends Object任务可以安排一次执行,或定期重复执行。 
对应于每个Timer对象是单个后台线程,用于依次执行所有定时器的所有任务。
void schedule(TimerTask task, Date time) 
在指定的时间安排指定的任务执行。  
void schedule(TimerTask task, Date firstTime, long period) 
从指定 的时间开始 ,对指定的任务执行重复的 固定延迟执行 。 

2.public abstract class TimerTask
extends Object
implements Runnable可以由计时器进行一次性或重复执行的任务。
boolean cancel() 
取消此计时器任务。  
abstract void run() 
该定时器任务要执行的操作。  
long scheduledExecutionTime() 
返回此任务最近 实际执行的 预定执行时间。 
	 * @throws InterruptedException 

	 */
	public static void main(String[] args) throws InterruptedException {
		Timer t = new Timer();
		t.schedule(new MyTimerTask(), new Date(120,2, 27, 19, 27, 50) ,1000);
		while(true){
			Thread.sleep(1000);
			System.out.println(new Date());
		}
	}

}
//任务类
class MyTimerTask extends TimerTask{

	@Override
	public void run() {
		
			System.out.println("起床时间到");

		}
	
	
}

3.等待唤醒机制

public class DemoWait {

	/**
	 * @param args
进程间的通信,等待唤醒机制
		void notify() 
				唤醒正在等待对象监视器的单个线程。  
		void wait() 
				导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。 
	 */
	public static void main(String[] args) {
		final printer p = new printer();
		
		new Thread(){
			public void run(){
				while(true){
					try {
						p.print1();
					} catch (InterruptedException e) {
						
						e.printStackTrace();
					}
				}
			}
		}.start();
		
		new Thread(){
			public void run(){
				while(true){
					try {
						p.print2();
					} catch (InterruptedException e) {
						
						e.printStackTrace();
					}
				}
			}
		}.start();
		
	}

}

class printer{
	private int flag = 1;
	public void print1() throws InterruptedException{
		synchronized(this){
			if(flag != 1){
				this.wait();          //线程等待
			}
			System.out.print("博");
			System.out.print("士");
			System.out.print("生");
			System.out.println();
			flag = 2;
			this.notify();               //唤醒单个线程
		}
	}
	
	public void print2() throws InterruptedException{
		synchronized(this){
			if(flag!=2){
				this.wait();
			}
			System.out.print("研");
			System.out.print("究");
			System.out.print("生");
			System.out.println();
			flag =1;
			this.notify();
		}
	}
}

4.1,在同步代码块中,用哪个对象锁,就用哪个对象调用wait方法
2,为什么wait方法和notify方法定义在Object这类中?
因为锁对象可以是任意对象, object是所有的类的基类,所以wait方法和notify方法需要定义在Object这个类中
3, sleep方法和wait方法的区别?
a,sleep方法必须传入参数,参数就是时间,时间到了自动醒来
wait方法可以传入参数也可以不传入参数,传入参数就是在参数的时间结束后等待,不传入参数就是直接等待
b, sleep方法在同步函数或同步代码块中,不释放锁
wai t方法在同步函数或者同步代码块中,释放锁|
5.

  • 三个线程间的通信

1.public class ReentrantLock extends Object
implements Lock, Serializable一个可重入互斥Lock具有与使用synchronized方法
和语句访问的隐式监视锁相同的基本行为和语义,但具有扩展功能。
void lock() :获得锁。
void unlock() :释放锁。
Condition newCondition()
返回一个新Condition绑定到该实例Lock实例。
2.public interface Condition Condition因素出Object监视器方法( wait , notify和notifyAll )成不同的对象,
以得到具有多个等待集的每个对象,通过将它们与使用任意的组合的效果Lock个实现。
Lock替换synchronized方法和语句的使用, Condition取代了对象监视器方法的使用。
void await() :导致当前线程等到发信号或 interrupted 。
void signal() :唤醒一个等待线程

public class DemoLock {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		final Printer12 p  = new Printer12();
		new Thread(){
			public void run(){
				try {
					while(true)
					p.print1();
				} catch (InterruptedException e) {
					
					e.printStackTrace();
				}
			}
		}.start();
		
		new Thread(){
			public void run(){
				try {
					while(true)
					p.print2();
				} catch (InterruptedException e) {
					
					e.printStackTrace();
				}
			}
		}.start();
		
		new Thread(){
			public void run(){
				try {
					while(true)
					p.print3();
				} catch (InterruptedException e) {
					
					e.printStackTrace();
				}
			}
		}.start();
	}

}

class Printer12{
	private  int flag = 1;
	private ReentrantLock r =new ReentrantLock();
	private Condition c1 = r.newCondition();
	private Condition c2 = r.newCondition();
	private Condition c3 = r.newCondition();
	public void print1() throws InterruptedException{
		
		r.lock();
		if(flag!=1){
			c1.await();
		}
		System.out.print("博");
		System.out.print("士");
		System.out.print("生");
		System.out.println();
		flag = 2;
		c2.signal();
		r.unlock();
	}
public void print2() throws InterruptedException{
	
	r.lock();
	if(flag!=2){
		c2.await();
	}
	System.out.print("研");
	System.out.print("究");
	System.out.print("生");
	System.out.println();
	flag = 3;
	c3.signal();
	r.unlock();
	}
public void print3() throws InterruptedException{
	r.lock();
	if(flag!=3){
		c3.await();
	}
	System.out.print("大");
	System.out.print("学");
	System.out.print("生");
	System.out.println();
	flag = 1;
	c1.signal();
	r.unlock();
}
}

6.线程组
1.public class ThreadGroup extends Object
implements Thread.UncaughtExceptionHandler线程组代表一组线程。 此外,线程组还可以包括其他线程组。
线程组形成一个树,除了初始线程组之外,每个线程组都有一个父进程。
允许线程访问有关其线程组的信息,但不能访问有关其线程组的父线程组或任何其他线程组的信息。
ThreadGroup(String name)
构造一个新的线程组。
ThreadGroup(ThreadGroup parent, String name)
创建一个新的线程组。
2.Thread(ThreadGroup group, Runnable target, String name)
分配一个新的 Thread对象,使其具有 target作为其运行对象,具有指定的 name作为其名称,属于 group引用的线程组。

public class DemoThreadGroup {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		MyRunnabler mr  = new MyRunnabler();         //创建Runnable接口的子类对象
		ThreadGroup tg = new ThreadGroup("线程组集合");    //创建一个线程组
		
		Thread t1 = new Thread(tg, mr, "线程1");              //创建一个新线程放入tg线程组中
		Thread t2 = new Thread(tg, mr, "线程2");
		
		System.out.println(t1.getThreadGroup().getName());    // 输出其所在的线程组
		System.out.println(t2.getThreadGroup().getName());
		System.out.println(tg);
	}

}

class MyRunnabler implements Runnable{

	@Override
	public void run() {
		
	}
	
}

7.线程的五种状态
在这里插入图片描述
8.线程池
public interface ExecutorService extends Executor一个Executor ,提供方法来管理终端和方法,
可以产生Future为跟踪一个或多个异步任务执行。 一个ExecutorService可以关闭,这将导致它拒绝新的任务。
提供了两种不同的方法来关闭ExecutorService 。 shutdown()方法将允许先前提交的任务在终止之前执行,
而shutdownNow()方法可以防止等待任务启动并尝试停止当前正在执行的任务。

void shutdown()
启动有序关闭,其中先前提交的任务将被执行,但不会接受任何新任务。
Future<?> submit(Runnable task)
提交一个可运行的任务执行,并返回一个表示该任务的未来。

public class Executors
extends Object工厂和工具方法Executor , ExecutorService , ScheduledExecutorService , ThreadFactory和Callable在此包中定义的类。 该类支持以下几种方法:
创建并返回一个ExecutorService设置的常用的配置设置的方法。
创建并返回一个ScheduledExecutorService的方法, 其中设置了常用的配置设置。
创建并返回“包装”ExecutorService的方法,通过使实现特定的方法无法访问来禁用重新配置。
创建并返回将新创建的线程设置为已知状态的ThreadFactory的方法。
创建并返回一个方法Callable出的其他闭包形式,这样他们就可以在需要的执行方法使用Callable 。

static ExecutorService newFixedThreadPool(int nThreads)
创建一个线程池,该线程池重用固定数量的从共享无界队列中运行的线程。

public class DemoExecuServise {

	/**
	 * @param args

	 */
	public static void main(String[] args) {
		ExecutorService pool = Executors.newFixedThreadPool(2);  //创建线程池
		
		pool.submit(new MyRunnabler1());              //把新建的线程放进线程池中执行
		pool.submit(new MyRunnabler1());              
		
		pool.shutdown();                                         //关闭线程池
	}
}

class MyRunnabler1 implements Runnable{

	@Override
	public void run() {
		for(int i = 0;i<1000;i++){
			System.out.println(Thread.currentThread().getName()+"......"+i);
		}
	}
	
}

9.多线程

public class DemoServise {

	/**
	 * @param args
1.public interface Callable<V>返回结果并可能引发异常的任务。 实现者定义一个没有参数的单一方法,称为call 。 
Callable接口类似于Runnable ,因为它们都是为其实例可能由另一个线程执行的类设计的。
 然而,A Runnable不返回结果,也不能抛出被检查的异常。 
该Executors类包含的实用方法,从其他普通形式转换为Callable类。 
V call() 
计算一个结果,如果不能这样做,就会抛出一个异常。  
2.public interface Future<V>A Future计算的结果。 提供方法来检查计算是否完成,等待其完成,并检索计算结果。 
结果只能在计算完成后使用方法get进行检索
	 * @throws ExecutionException 
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		ExecutorService poll = Executors.newFixedThreadPool(2);
		
		Future< Integer> f1 = poll.submit(new MyCallable(100));
		Future< Integer> f2 = poll.submit(new MyCallable(1000));
		System.out.println(f2.get());
		System.out.println(f1.get());
	}

}

class MyCallable implements Callable<Integer>{
	private int num ;
	public MyCallable(int num){
		this.num = num;
	}
	@Override
	public Integer call() throws Exception {
		int sum  = 0;
		for(int i = 1;i<num;i++){
			sum+=i;
		}
		return sum;
	}
	
}
public class test1 {

	/**
	 * @param 
	 1.简单工厂模式:又叫静态工厂方法模式,它定义一个具体的工厂类来创建一些类的实例。
	 2.优点:客户端不需要再负责对象的创建,从而明确了各个类的职责。
	 3.缺点:这个静态工厂负责所有类的 创建,如果有新的类增加,就需要不断的修改工厂类,不利于后期的维护。
	 案例:动物抽象类Animal 猫类Cat 狗类Dog AnimalFactory动物工厂类  
	 */
	public static void main(String[] args) {
		Dog d = (Dog) AnimalFactory.CreatAnimal("dog");
		Cat c = (Cat) AnimalFactory.CreatAnimal("cat");
		d.eat();
		c.eat();
	}

}
//动物抽象类
public abstract class Animal {
public abstract void eat();
}
//猫类
public class Cat extends Animal {

	@Override
	public void eat() {
		System.out.println("猫吃鱼");
	}

}

//狗类

public class Dog extends Animal {

	@Override
	public void eat() {
		System.out.println("狗吃肉");
	}

}

//动物工厂类

public class AnimalFactory {
public static Animal CreatAnimal(String name){
	if("dog".equals(name)){
		return new Dog();
	}else if("cat".equals(name)){
		return new Cat();
	}else{
	return null;
	}
}
}
public class test2 {

	/**
	 * @param args
	 * 工厂方法模式:
	 * 1.工厂方法模式中抽象工厂类负责定义创建对象的接口,具体对象的创建由实现了抽象工厂的具体类实现
	 * 2.优点:客户端不需要再负责对象的创建,从而明确了各个类的职责,如果有新的对象增加,只需要增加一个具体的类
	 * 和具体的工厂类即可,不影响已经有的代码,后期的维护容易,增强了系统的扩展性。
	 * 3.缺点:需要额外的增加代码,增加了工作量。 
动物抽象类: public abstract Animal { public abstract void eat(); }
厂接口: public interface Factory {public abstract Animal createAnima1();}
具体狗类: public class Dog extends Animal
具体猫类:public class Cat extends Animal
开始,在测试类中每个具体的内容自己创建对象,但是,创建对象的工作如果比较麻烦,就需要有人专门做这个事情,所以就知道了-一个专门的类来创建对象。发现每次修改代码太麻烦,用工厂方法改进,
针对每一个具体的实现提供-一个具体工厂。
狗工厂:public Class DogFactory implements Factory {
public Animal createAnimal() {}
猫工厂:public class CatFactory implements Factory {
public Animal createAnimal() {}

	 */
	public static void main(String[] args) {
		DogFactory df =new DogFactory();      //创建狗工厂
		Dog d = (Dog) df.CreateFactory();
		d.eat();
	}

}
public interface Factory {
	public Animal CreateFactory();
}
public class DogFactory implements Factory {

	@Override
	public Animal CreateFactory() {

		return new Dog();
	}

}
public class CatFactory implements Factory {

	@Override
	public Animal CreateFactory() {

		return new Cat();
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值