线程初学

在这里插入图片描述

  1. 并发:指两个或多个事件在同一个时间段发生,交替执行
  2. 并行:指两个或多个事件在同一时刻发生
    在这里插入图片描述
    在这里插入图片描述
    进程:指一个内存中运行的程序,每一个进程都有一个独立的内存空间,一个应用程序可以运行多个进程,进程也是程序的一次执行过程,是系统运行程序的基本单位,系统运行一个程序就是一个进程从创建,运行到消亡的过程。
    线程:是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程,如果有多个线程,当前程序就叫多线程程序
    理解:应用程序=软件 进程=功能模块 线程=方法
    多线程的好处:
    1 效率高
    2 多个线程之间互不干扰

线程调度
1 分时调度:所有线程轮流使用CPU的使用权,平均分配CPU的使用时间
2 抢占式调度:优先级高的先调用,相同优先级则随机调用
Java使用的是抢占式调度

main()就是主线程

创建线程
1 继承Tread类
在这里插入图片描述
2 实现Runable接口
在这里插入图片描述
2 实现Runable接口比继承Tread类更加具有优势
1 多态,可维护性
不同点:继承Tread类的线程类本身是一个线程类的子类,所以可以继承Tread类的start()来开启线程,而Runable接口的实现类并不是Tread类,所以并不可以使用start()来开启线程,需要Tread类的实例对象并且传入Runable接口的实现类对象来开启线程。

简化代码:使用匿名内部类
在这里插入图片描述
3 实现Callable接口
1 可以有返回值
2 可以抛出异常

public class MyCallable {

	public static void main(String[] args) throws InterruptedException, ExecutionException {
	
		for (int j = 0; j < 200; j++) {
			System.out.println("线程名称"+Thread.currentThread().getName()+"执行"+j+"步");
		}
	
		
		TestCallable t1 = new TestCallable();
		TestCallable t2 = new TestCallable();
		TestCallable t3 = new TestCallable();
		
		//创建执行服务
		ExecutorService service = Executors.newFixedThreadPool(3);
		
		//提交执行
		Future<Integer> submit1 = service.submit(t1);
		Future<Integer> submit2 = service.submit(t2);
		Future<Integer> submit3= service.submit(t3);
		
		//获取结果
		Integer rs1 = submit1.get();
		Integer rs2= submit2.get();
		Integer rs3 = submit3.get();

		//关闭服务
		service.shutdown();

	}

}


class TestCallable  implements Callable<Integer>{
	private Integer i;

	@Override
	public Integer call() throws Exception {
		for (int i = 0; i < 200; i++) {
			
			System.out.println("线程名称"+Thread.currentThread().getName()+"执行"+i+"步");
		}
		
		
		
		return i;
	}
	
	
}

线程安全
1 重复代码:不同线程同时执行到了同一个语句(并行)
2 出现不存在的:在不同的线程中,执行过判断语句后,此线程的CPU执行权就被抢走,由其它线程开始执行,进过及格线程执行之后就会出现不存在的数(并发)

解决方法
1 同步代码块(不局限于一个对象)
锁对象一般是共享数据的代码,需要变化的量,即是需要增删改的 数据
在这里插入图片描述
2 同步方法(局限于只有一个对象)
synchronize 关键词,默认锁 是它的所在的类本身

在这里插入图片描述
同步方法的锁对象就是实现类对象

如果是静态的同步方法,锁对象就不是实现类对象,因为静态方法优先于对象
静态方法的锁对象是本类的class属性——class文件对象(反射)
3 锁
在这里插入图片描述
注意事项:在同步代码块和同步代码方法中,锁对象可以是任意对象,但是多线程之间必须是同一个对象
锁对象作用:把代码块锁住,使其只在一个线程类执行

线程通信
1 为什么要处理线程间通信:多个线程并发执行时,在默认情况下CPU是随机切换线程的,当我们需要多个线程来共同执行完成一件任务,并且我们需要他们之间有规律的运行,那么多线程之间需要一些协调通信,以此来帮我们达到多线程共同操作一份数据
2 如何保证线程之间通信有效利用:多个线程在处理同一个资源,并且任务不同时,需要线程通信来帮助解决线程之间对同一个变量的使用和操作。就是多线程在操作同一份数据时,避免对同一共享变量的争夺。也就是说,需要一种手段来使各个线程能有效的利用资源,这种手段叫做——等待唤醒机制

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

1 wait()与notify()必须要由同一个锁对象调用,因为对应的锁对象可以通过notify()唤醒使用同一个锁对象调用的wait()后的线程
2 wait()和notify()都是属于object类的方法,因为锁对象可以是任意对象,而任意对象都是继承了object类
3 wait()和notify()必须在同步代码块或者同步代码方法中执行,因为,必须调用锁对象才可以调用这两个方法
4 每一个对象都有一把锁,sleep()方法不会释放锁
5 yield() 礼让方法,礼让线程,但是不一定成功
6 join(),插队方法,只有当插入的线程执行完成之后才可以继续执行下去,否则线程进入堵塞状态
9 wait()会释放锁,sleep()方法不会释放锁;wait() 需要在同步代码块中使用,sleep() 可以在任何地方使用
在这里插入图片描述
7 线程对象.setPriority() 和 getPriority(),是对于线程优先级的调度,但是线程优先级高的不一定先执行,优先级的高低只决定被CPU调用的概率,必须要先设置优先级再启动线程,不然无效

死锁
:多个线程互相持有对方需要的资源,形成僵持
避免方法:
1 不要形成锁嵌套
2 资源不共用
3 不要形成循环
4 可剥夺条件

线程池
背景:线程频繁的创建和销毁,特别消耗资源,若在并发编程下,性能将会受到很大的影响
优点:
1 提高了响应速度(减少了新线程的创建时间)
2 降低了资源消耗(重复利用线程池中的线程,减少了创建时间)
3 便于线程管理
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值