java重点基础:线程和同步锁和线程通信

学习线程的主要知识点概要如下:

                                                    

进程和线程的区别:

 *     1.进程:操作系统而言,进程就是程序,多进程就是多个程序同时执行
 *         一个进程包含一个~多个线程,每一个进程都有自己的代码和运行空间,进程之间切换开销较大,进程是资源分配的最小单位
 *     2.线程:程序中的顺序流,多线程:一个程序中的多个顺序流同时执行
 *         一系列线程共享代码和数据空间,每个线程都有自己的程序计数器,
线程之间切换开销较小,线程是cpu调度的最小单位

线程和进程的状态:  新生  就绪   运行  阻塞   终止   

CPU只会给就绪状态和运行状态的线程时间片,不会给阻塞状态的

新生状态:线程创建完就是新生状态

就绪状态:当调用start()方法就是进入就绪状态,等待CPU给时间片,不给时间片不执行,时间片用完了也进入就绪状态

运行状态:当CPU给之间片真正执行的时间,当时间片用完了,继续回到就绪状态

阻塞状态:在阻塞状态时,CPU必定不会给时间片,因为被阻塞了,必须等待其进入到就绪状态才行

终止状态:线程被终止了

 

如何进入到就绪状态
 *     1.start()
 *     2.阻塞解除
 *     3.线程切换,被切换的线程进入到就绪状态
 *     4.yield()    礼让线程

如何进入到阻塞状态

1.sleep(毫秒数) 方法       当时间结束了就自动回到就绪状态

2.join()方法                     当被插队的结束了才能回到就绪状态

3.wait()方法                   一直等待,直到被notify()方法唤醒才能进入到就绪状态

thread.join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程t的join()方法,直到线程t执行完毕后,才会继续执行线程B。

  • t.join();      //在B线程中使调用线程 t 在此之前执行完毕。
  • t.join(1000);  //在B线程中,等待 t 线程,等待时间是1000毫秒

 

注意:如果线程被生成了,但还未被起动,调用它的 join() 方法是没有作用的,将直接继续向下执行

如何让一个线程进入到终止状态
1.正常执行完毕    

2.destroy() |stop()      已过时     

3.通过标识手动判断

sleep() 线程休眠
 *     1.模拟网络延迟
 *     2.放大问题的可能性
 *     抱着资源睡觉,同步的对象资源,让出cpu的资源 

yield() 有这个方法的线程是高风亮节,礼让线程

当A,B线程同时开启时候,当A中有yield()方法,在执行A中的方法时候,遇到yield方法,这个线程就回到就绪状态,再次调用的时候就会接着上次没有执行的代码向下执行!!!!!!!!!!!!!!!!!!

 

如何创建一个线程

 *     1) 继承Thread,重写run()方法
 *         1)在run()方法中定义线程体
 *         2)开启: 使用start()方法开启线程
 *     2) 实现Runnable接口,重写run()方法  推荐
 *     3) 实现Callable接口,重写call()方法
 

第一种:单继承Thread类,重写run方法:

public class ThreadDemo01 extends Thread{
	//多线程的线程体
	@Override
	public void run() {
		for(int i=1;i<=20;i++){
			System.out.println("一遍吃饭...");
		}
	}

        public static void main(String[] args) {
		//开启多线程 创建线程
		ThreadDemo01 th=new ThreadDemo01();
		th.start();    		//开启线程
		//th.run();   注意:这是方法的调用,不是多线程的开启
		for(int i=1;i<=20;i++){
			System.out.println("一遍说话...");
		}
		//th.start();   放在这里的话:主线程中代码执行完毕,只剩下一个th线程,看不到线程切换的效果
	}
}

第二种,实现runnable接口,避免单继承的局限性,推荐使用

public class ThreadDemo02 implements Runnable{
	//定义线程体的方法,当被调用的时候,会逐行执行里面的代码
	@Override
	public void run() {
		for(int i=1;i<=10;i++){
			System.out.println("一遍敲代码...");
		}
	}
	
	public static void main(String[] args) {
		ThreadDemo02 th=new ThreadDemo02();//创建线程
		//开启线程
		Thread t=new Thread(th);  //因为开启线程的方法在Thread类中,Thread做为代理类出现,静态代理
		t.start();
		for(int i=1;i<=10;i++){
			System.out.println("一遍陪女朋友...");
		}
	}
}

练习:

 * 模拟12306 
 *     需求: 100张票,3个人买完
 *     资源共享: 100张票

下面的代码会造成多人抢到一张票的问题,待优化

在创建线程的时候Thread th1=new Thread(web,"王冬冬");th1作为代理出现,web指的是代理哪一个线程,第二个指的是线程名

public class Web12306_03 implements Runnable{
	//成员 资源
	int tikets=100;
	@Override
	public void run() {
		//循环买票
		while(true){
			if(tikets<=0){
				break;
			}
			try {
				Thread.sleep(1);  //线程睡眠100ms
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"正在购买第"+tikets--);
		}
	}
	
	public static void main(String[] args) {
		Web12306_03 web=new Web12306_03();
		//开启三个线程
		Thread th1=new Thread(web,"王冬冬");
		Thread th2=new Thread(web,"王宇晨");
		Thread th3=new Thread(web,"郭友波");
		th1.start();
		th2.start();
		th3.start();
	}
}

线程的优先级

 * 线程的优先级: 提高优先执行的可能性,但是不一定就会先执行
 *     void setPriority(int newPriority) 更改线程的优先级。 
 *     1~10 1最小  10最大
 *     Thread.NORM_PRIORITY 5
 *     Thread.MAX_PRIORITY  10
 *     Thread.MIN_PRIORITY  1

可以直接输入数字                th.getPriority()    //5/10/1/...         th.getState()//获得状态      new  /   runnable    time_waiting


synchronized  同步锁

锁方法简单,但是效率低,因为锁的是整个,要效率可以锁代码块

 * 线程安全:
 *     多个线程同时操作同一个资源的时候,才可能会出现线程安全问题,例如上述的抢票
 * 
 * 通过同步synchronized关键字控制线程安全:
 *     同步方法 
 *         静态方法
 *         成员方法
 *     同步块 synchronized(类的class对象|this|资源){代码}      锁住的必须是不可变的
 *         类: 类名.class 一个类的Class对象 一个类只有一个Class对象   this和static不能同时使用      
 * 
 *  锁要锁着不变的东西,会变的锁不住,锁住资源
 *  同步的范围 {} 中的内容太大,效率低,同步的范围太小,锁不住
 *  单例模式:懒汉式

public static synchronized Single newInstance(){
		System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");
		System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");
		System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");
		System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");
		System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");
		if(single==null){
			single=new Single();
		}
		return single;
	}
public static Single newInstance(){
		System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");
		System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");
		System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");
		System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");
		System.out.println("啦啦啦啦啦啦啦啦啦啦啦啦");
		synchronized (Single.class) {  //控制多线程排队执行
			if(single==null){
				System.out.println("-----------------------");
				single=new Single();
			}
		}  //{}中的代码就是排队执行的代码
		return single;
	}

synchronized 可以锁类,可以锁this,可以锁资源

当锁类的时候,相当于把这个类的所有对象整个锁住了

同步this,同步当前对象,锁住这个对象,这个对象的所有资源都被锁住了

如果只想要锁住其中某个资源,可以只锁这个资源,一般是成员变量

线程通信

 *     wait() 和 notify()通过操作同一份资源控制线程的通信,方法必须使用在同步的环境下
 *     wait()进入到对象(资源)的等待池中排队等待,等待被唤醒,会让出cpu的资源,同时也会释放对象的锁
 *         sleep() 让出cpu的资源,不会释放对象的锁
 *     notify() 唤醒正在等待的线程,只是具备了可执行的能力,就绪状态,如果想要执行,除了获取cpu的资源以外,还要拿到对象的锁

public class Demo01 extends Object{
	public static void main(String[] args) {
		Street street=new Street();
		new Thread(new Person(street)).start();
		new Thread(new Car(street)).start();
	}
}
class Street{
	//信号灯
	boolean flag=false;
	
	//we 东西 false
	public void we(){
		if(flag==true){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}else{
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("车走...");
			flag=true;
			this.notify();
		}
	}
	//ns 南北 true
	public void ns(){
		if(flag==false){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}else{
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("人走...");
			flag=false;
			this.notify();
		}
	}
}
//人
class Person implements Runnable{
	Street street=null;  //街道

	
	public Person(Street street) {
		super();
		this.street = street;
	}


	@Override
	public  void run() {
		synchronized (street) {
			while(true){
				street.ns();
			}
		}
	}
}
class Car implements Runnable{
	Street street=null; //街道
	public Car(Street street) {
		super();
		this.street = street;
	}
	@Override
	public synchronized void run() {
		synchronized (street) {
			while(true){
				street.we();
			}
		}
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值