CoreJava学习笔记09 线程

多线程

进程: 操作系统(OS)并发的一个任务
并发原理: CPU分时间片, 多个任务交替执行 宏观并行, 微观串行. 由OS调度
线程: 一个进程中并发的一个顺序执行流程

线程的组成:

  1. CPU
  2. 数据空间 堆空间共享, 栈空间独立 (每个线程都会有自己的栈空间 , 多个线程共享同一个堆空间)
  3. 代码
  • 实现Runnable接口. 实现 run() 方法

    class Task implements Runnable{
    	public void run() {
    		for(int i = 1 ; i <= 10000 ; i++) {
    			System.out.println("AAA "+i);
    		}
    	}
    }
    Runnable task = new Task();  // 任务
    Thread t1 = new Thread(task); // 创建线程对象
    t1.start();
    
  • 继承Thread类, 覆盖run()方法

    class MyThread extends Thread{
    	public void run() {
    		for(int i = 1 ; i <= 10000 ; i++) {
    			System.out.println("BBB "+i);
    		}
    	}
    }
    Thread t2 = new MyThread();		
    t2.start();
    
线程的状态

在这里插入图片描述

线程池 (Thread Pool) JDK5

当线程的任务结束, 线程不终止, 避免反复创建和销毁线程, 重用线程资源, 提升效率

可以将多个任务分配给一个线程,线程结束任务A , 还可以去执行任务B

对于固定长度的线程池, 可以控制最大并发数

		Runnable task1 = new TaskA();
		Runnable task2 = new TaskB();
			
		ExecutorService es = Executors.newFixedThreadPool(2);
		es.submit(task1);
		es.submit(task2);
		
		es.shutdown();
Callable接口 取代Runnable 有返回值, 可以抛异常
		Callable<Integer> task1 = new TaskA();
		Callable<Integer> task2 = new TaskB();
			
		ExecutorService es = Executors.newCachedThreadPool();
		Future<Integer> f1 = es.submit(task1);
		Future<Integer> f2 = es.submit(task2);
		
		Integer result1 = f1.get();
		Integer result2 = f2.get();
		
		System.out.println(result1 + result2);

线程的同步

多线程访问同一个对象 (临界资源) , 如果破坏了原子操作, 就会导致数据不一致

 synchronized (obj) {      //   对 obj 对象加锁的同步代码块
 	
 } 
 每个对象都有一个互斥锁 (monitor), 用来分配给线程 
 线程只有拿到obj的锁,才能进入对obj加锁的同步代码块
 线程离开同步代码块, 会释放对应的锁
 
 
 public synchronized void m(){}  // 同步方法     方法实现: 对this加锁的同步代码块
 线程只有拿到obj的锁,才能调用obj的同步方法
 线程结束对obj同步方法的调用, 会释放obj的锁 

ArrayList 线程不安全 并发效率高

Vector 线程安全 所有方法都是同步方法 并发效率低 1.0 (淘汰)

线程安全的集合类 JDK5
  • CopyOnWriteArrayList List

    不修改原有数组, 通过复制新数组的方式完成List中的修改操作. 查询场景远多于修改场景

  • ConcurrentHashMap Map

    JDK5 - JDK7 分段锁 把Map分为16个片段, 每个片段独立加锁

    JDK8 CAS(Compare And Swap) 比较交换算法 无锁算法

  • CopyOnWriteArraySet Set

  • ConcurrentLinkedQueue Queue 队列 (FIFO)

    CAS 无锁算法, 实现线程安全

  • 接口 BlockingQueue (Queue的子接口 当使用队列的条件不满足时自动阻塞)

    • ArrayBlockingQueue

      数组实现 有界阻塞队列 数组满时添加元素的线程会阻塞;数组空时删除元素的线程会阻塞

    • LinkedBlockingQueue

      链表实现 无界阻塞队列 链表为空时删除元素的线程会阻塞

死锁 - 等待通知机制
synchronized(o1){
    t1
    synchronized(o2){
        
    }
}

synchronized(o2){
    t2
	synchronized(o1){
    }
}
  • wait() 来自Object obj.wait() 必须放在对obj加锁的同步代码块 . 执行结果:线程释放锁标记, 进入阻塞

  • notify() / notifyAll() 来自Object obj.notify()/obj.notifyAll() 必须放在对obj加锁的同步代码块

    执行结果: 通知对obj阻塞的 一个/全部 线程可以离开阻塞状态 线程不会释放锁标记

wait() 和 sleep() 有什么区别 ? wait()释放锁标记, sleep()不释放锁标记

单例模式

设计一个类 , 这个类只能有一个对象

饿汉式实现     缺点: 无论对象是否需要, 都先把对象创建好. 可能浪费空间
class ClassA{
	private static ClassA instance = new ClassA();
	public static ClassA newInstance() {
		return instance;
	}
	private ClassA() {}
}
懒汉式实现     缺点: 并发效率低
class ClassB{
	private static ClassB instance = null;
	public static synchronized ClassB newInstance() {
		if (instance == null) instance = new ClassB();
		return instance;
	}
	private ClassB() {}
}
class ClassC{
	private static class Holder{
		static ClassC instance = new ClassC();
	}
	public static ClassC newInstance() {
		return Holder.instance;
	}
	private ClassC() {}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值