10.17Java - 多线程

多线程

多线程示例:

一家公司账户有100元,这天两个会计同时操作了公司的银行账户,会计A取50,会计B存100,可能会发生以下几种情况:

  1. 账户余额变成50(A和B同时读到了账户余额等于100,A最后更改了账户)
  2. 账户余额变成200(A和B同时读到了账户余额等于100,B最后更改了账户)
  3. 账户余额变成150 (A和B顺序读取到账户余额)

1、进程

  1. 是执行中的应用程序
  2. 一个进程可以包含一个或多个线程
  3. 一个进程至少要包含一个线程(比如Java中运行main方法的主线程)

比如:B站看视频的同时,还可以点赞收藏等等,这些操作都是Bilibili这个应用程序的子任务,也就是这个进程的子任务

2、线程

  1. 线程本身依靠进程(程序)运行
  2. 线程是程序中的顺序控制流,只能使用分配给程序(进程)的资源和环境

解释:运行一个Java程序的实质是启动一个Java虚拟机进程,也就是说一个运行的Java程序就是一个Java虚拟机进程。

线程是进程中可独立执行的最小执行单元,一个进程中有多个进程,同一线程中的线程共享该进程的资源(内存、空间、变量、方法)

2.1、单线程

程序中只存在一个主线程,实际上主方法(main)就是一个主线程

线程是进程中所要完成的一个计算过程,也被称为进程的任务

2.2、多线程

多线程是在一个进程中同时运行多个任务

多线程的目的:更好的使用cpu资源,提高程序的计算效率

2.3、串行、并行、并发

2.3.1 串行:一个人做一件件做所有任务
2.3.2 并发:一个人,交替的做多个任务

​ 即一个人先执行一个任务,在这个任务执行期间,有一段时间人是空闲的,他利用这段时间再去执行另一个任务,这样交替执行任务。

示例:蒸馒头的同时,馒头没熟之前,这段时间可以拖地、洗衣服等等

2.3.3 并行:多个人,同时做多个任务;总耗时取决于耗时最长的任务

3、创建线程的方式

  1. 继承Thread类,extends Thread
  2. 实现Runable接口,implement Runable
  3. 通过Collection接口和FutureTask对象创建线程
  4. 通过线程创建对象

创建线程

//方法1
package d17thread;

public class Demo {
	public static void main(String[] args) {
		CrThr c = new CrThr();
		c.start();
	}
}

class CrThr extends Thread{
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("创建线程");
	}
	
}
//方法2
package d17thread;

public class Demo {
	public static void main(String[] args) {
		CrThr c = new CrThr();
		Thread t = new Thread(c);
		t.start();
	}
}

class CrThr implements Runnable{
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("创建线程");
	}
	
}

package d17thread;

/*创建线程类的方式
 * 1.继承Thread类,extends Thread
 * 2.实现runable接口,implements Runable
 * 3.通过Callable接和FutureTask对象创建线程
 * 4.通过创建线程池创建对象
 */
public class Test {
	public static void main(String[] args) {
		//创建线程对象
		Worker w = new Worker();
		w.setName("tt1");
		//启动线程类
		w.start();
		/*
		 * 调用start()方法不是立即调用run()
		 * 而是先去争用cpu时间片,一旦获取cpu时间片,才会去调用run()方法
		 */
		
		Worker2 w2 = new Worker2();
		Thread t = new Thread(w2,"t1");
		t.start();
	}
}



class Worker extends Thread{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		/*
		 * sleep()属于Thread类,wait()类属于Object类
		 * sleep()方法表示线程休眠指定的时间,休眠时间结束,线程继续执行
		 * wait()方法表示线程等待,此时线程会让出cpu资源,知道其他线程通过nodify()/nodifyAll()方法唤醒该线程
		 * 
		 */
		try {
			sleep(1000);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		try {
			wait();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("线程开始执行");
	}
	
}
class Worker2 implements Runnable{
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 10; i++) {
			
			
			System.out.println(i);
		}
		System.out.println("重写Runable接口");
	}
}


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p8f51hCX-1666355724888)(C:\Users\19912\AppData\Local\Temp\1665997650707.png)]

3.1、线程的一生

新建、就绪、运行、阻塞、死亡

  1. 新建:创建线程对象后,即进入阻塞状态

  2. 就绪:当调用线程对象的start()方法,线程进入就绪状态,处于就绪状态的线程,只是说明该线程已经做好了准备,随时等待cpu调度执行,并不是说执行了start()方法线程就会立即执行

  3. 运行:当cpu开始调度处于就绪状态的线程时,此时线程才开始执行(执行run()方法),即进入运行状态,注意,就绪状态是进入到运行状态的唯一入口,也就是说,线程想要进入运行状态执行,首先必须处于就绪状态种

  4. 阻塞:处于运行状态中的线程由于某种原因,暂时放弃对cpu的使用权,停止执行,此时进入阻塞状态,直到其重新进入到就绪状态

    根据阻塞产生的原因不同,阻塞状态又分为三种

    1. 等待阻塞:运行状态中的线程执行Object.wait()方法
    2. 同步阻塞:线程在获取synchronized内部锁失败(因为所被其他线程占用)
    3. 其他阻塞:通过调用线程的Thread.sleeo()、join()方法或发出I/O请求时,线程会进入到阻塞状态,当sleep()状态超时(sleep休眠结束)、join()方法等待线程终止或超时,或者I/O处理完毕时,线程重新进入就绪状态
  5. 死亡:线程执行完毕或者因为异常推出了run()方法,该线程结束生命周期,线程销毁

4、线程的同步机制

同步机制:多个线程按照一定顺序执行的方案

4.1 同步锁 synchronized

  • Java 中的任何一个对象,都有唯一一个与之相关联的锁
  • 这种锁被称为监听器(monitor)或内部锁(Intrinsic Lock)
  • 内部锁是一种排它锁,即哪个线程拿到锁,该线程才能电泳同步方法,其他线程阻塞状态
  • 内部锁是通过synchronized关键字实现的
  • synchronized关键字可以用来修饰方法以及代码块
package d17thread;

public class Th1 {
	/*
	 * 同步机制:多个线程按照一定顺序执行的方案
	 * 
	 * 同步锁 synchronized
	 * 
	 * Java 中的任何一个对象,都有唯一一个与之相关联的锁
	 * 这种锁被称为监听器(monitor)或内部锁(Intrinsic Lock)
	 * 内部锁是一种排它锁,即哪个线程拿到锁,该线程才能电泳同步方法,其他线程阻塞状态
	 * 内部锁是通过synchronized关键字实现的
	 * synchronized关键字可以用来修饰方法以及代码块
	 */
	
	
	public static void main(String[] args) {
		Thre t = new Thre();
		t.start();
		Thre t1 = new Thre();
		t1.start();
	}
	static int count;
	static synchronized void add() {
		for (int i = 0; i < 80000; i++) {
			count++;
			System.out.println(count);
		}
	}

}
class Thre extends Thread{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		Th1.add();
	}
	
}
package d17thread;

public class Th1 {
	/*
	 * 同步机制:多个线程按照一定顺序执行的方案
	 * 
	 * 同步锁 synchronized
	 * 
	 * Java 中的任何一个对象,都有唯一一个与之相关联的锁
	 * 这种锁被称为监听器(monitor)或内部锁(Intrinsic Lock)
	 * 内部锁是一种排它锁,即哪个线程拿到锁,该线程才能电泳同步方法,其他线程阻塞状态
	 * 内部锁是通过synchronized关键字实现的
	 * synchronized关键字可以用来修饰方法以及代码块
	 */
	
	
	public static void main(String[] args) {
		Thre t = new Thre();
		t.start();
		Thre t1 = new Thre();
		t1.start();
	}
	static int count;
	static synchronized void add() {
		for (int i = 0; i < 80000; i++) {
			count++;
			System.out.println(count);
		}
	}

}
class Thre extends Thread{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		Th1.add();
	}
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值