黑马程序员--java基础--线程,单例设计模式


------- android培训java培训、期待与您交流! ---------




什么是线程:


  进程中的一个独立的控制单元。
  线程在控制着进程的执行
  线程会开启一个新的执行单元


启动jvm时会有一个进程java.exe

该进程有至少一个线程负责

该线程代码存在于main方法

该线程为主线程

创建线程的两种方式?

一、继承Thread类
1.定义类继承Thread类
2.复写run方法
  将自定义的代码存储在run方法中
3.调用线程的start方法
  该方法两个作用:启动线程,调用run方法


public class ThreadDemo {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 创建,并初始化Demo类型对象d  
		Demo d = new Demo("one_*");
		// 启动线程t1
		d.start();
	}
} 

class Demo extends Thread {
	
	Demo(String name){
		super(name);
	}
	// 重载run函数  
	public void run() {
			System.out.println("-----demo run----");	
	}
}



二、实现Runnable接口

class Ticket implements Runnable{
	//实现 Runnable接口
	//重写 Runnable接口中的run()方法
	public  void  run() {
			System.out.println("-----demo run----");
	}
}
public class ThreadDemo {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 创建,并初始化Ticket对象t 
		Ticket t = new Ticket();
		// 通过Thread创建线程	
		Thread t1 = new Thread(t);
		// 启动线程t1  
		t1.start();
	}
} 

线程类的一些常用方法:


  sleep(): 强迫一个线程睡眠n毫秒。 
  isAlive(): 判断一个线程是否存活。 
  join(): 等待线程终止。 
  activeCount(): 程序中活跃的线程数。 
  enumerate(): 枚举程序中的线程。 
    currentThread(): 得到当前线程。 
  isDaemon(): 一个线程是否为守护线程。 
  setDaemon(): 设置一个线程为守护线程。(用户线程和守护线程的区别在于,是否等待主线程依赖于主线程结束而结束) 
  setName(): 为线程设置一个名称。 
  wait(): 强迫一个线程等待。 
  notify(): 通知一个线程继续运行。 
  setPriority(): 设置一个线程的优先级。 




线程的五种状态
        1,新建状态
创建了一个新的线程
2,冻结状态
       放弃执行权。sleep。wait。
3,运行状态
就绪状态的线程获取了CPU的执行权
4,阻塞状态
有执行资格,没有执行权
1、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
        2、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
        3、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者 I/O处理完毕时,线程重新转入就绪状态。
5,死亡状态

退出了run方法,结束了生命周期







线程安全
同步代码块  synchronized(任何对象){
需要同步的代码块
}
对象如同锁,持有锁的线程才能在同步中执行
必须多个线程使用一个共同的锁


同步函数用this锁


静态同步函数用class对象


单例设计模式
在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象

实现方式
饿汉式:在类装载时构建实例。(一般认为这种方式要更加安全些)
        懒汉式:在第一次被使用时构建实例。 

	
	1:饿汉式
	public class Singleton1 {
 
 		//构造方式设为private,外部不能访问
 		private Singleton1() {
 		}
 		// 在自己内部定义自己的一个private实例,只供内部调用
 		private static final Singleton1 s = new Singleton1();
		 // 提供了一个供外部访问本class的静态方法,可以直接访问
 		public static Singleton1 getInstance() {
 			 return s;
 		}
	}
2:懒汉式
	public class Singleton2 {
 
		 private static Singleton2 s = null;
	
 		 private Singleton2{};

		 public static Singleton2 getInstance() {
  				
  			if (s == null){
				Synchronized(Singleton2.class){
					if(s == null)
					s = new Singleton2();
				}
   				
  			}
  
 			return s;
 		}
	}




线程的通信:

wait()与sleep()的区别:

wait():释放资源释放锁

sleep():释放资源不释放锁

package Thread;
/**
 * 线程间通信:
 * 多个线程的run方法不同
 * 等待线程存在线程池中
 * notifyAll()唤醒所以线程
 * wait notify notifyall都用在synchronized中
 * 因为要对持有监视器(锁)的线程操作
 * 为什么要定义在OBJECT类中
 * 
 * 因为这些方法在操作同步中的线程时,都必须要标识他们所操作线程持有的锁
 * 只有同一个锁上被等待的线程,可以被同一个锁上notify唤醒
 * 不可以对不同锁中的线程进行唤醒
 * 
 * 也就是说,等待和唤醒必须是同一个锁
 * 
 * 而锁可以是任意对象,
 */

class Res{//两个线程都在操作res这个资源
	private String name;
	private String sex;
	private boolean flag = false;
	public  synchronized void set(String name,String sex){
		if(flag)
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		this.name = name;
		this.sex = sex;
		flag = true;
		this.notify();
	}
	public synchronized void out() {
		if(!flag)
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		System.out.println(name + "...." + sex);
		flag = false;
		this.notify();
	}
}

class Input implements Runnable{
	private Res r;
	Input(Res r) {
		this.r = r;
	}
	public void run() {
		int x=0;
		while(true){
			synchronized (r){   //用资源这个锁
				
				if(x==0){
					r.set("mike", "man");				
				}
			
				else{
					r.set("丽丽", "女");
				}			
				x = (x+1) % 2;
				
			}
		}
	}
}

class Output implements Runnable{
	private Res r;
	Output(Res r) {
		this.r = r;
	}
	public void run() {		
		while(true){
			r.out();
		}
	}
}

public class ThreadDemo4 {

	public static void main(String[] args) {
			Res r = new Res();
			new Thread(new Input(r)).start();
			new Thread(new Output(r)).start();
//			Input in = new Input(r);
//			Output out = new Output(r);
//			Thread t1 = new Thread(in);
//			Thread t2 = new Thread(out);
//			t1.start();
//			t2.start();
	}

}



------- android培训java培训、期待与您交流! ---------


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值