Java多线程及一些处理方法

1.概念

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

2.线程的组成:
(1)CPU

特点:由OS负责分配

(2)Data

特点 : 堆空间共享 栈空间独立
堆空间: 存储对象 (存储实例变量)
栈空间: 存储局部变量

(3)代码

由程序员指定 :继承Thread类(覆盖run())或者实现Runnable接口中的run()

3.状态关系图

在这里插入图片描述

4.join和sleep方法

一个Thread对象代表一个线程 当线程t1对线程t2调用join() 则t1阻塞 当t2进入终止状态时,t1回到可运行状态

package day17hot1;
public class TestThread2 {
	public static void main(String[] args) {
		Thread t1 = new ThreadA();
		Runnable t2 = new ThreadB(t1);
		Thread t3 = new Thread(t2);
		t1.start();
		t3.start();
	}
}

class ThreadA extends Thread{
	public void run() {
		for(int i = 1;i <= 99;i+=2) {
			System.out.println("***" + i);
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

class ThreadB implements Runnable{
	Thread t;
	public ThreadB(Thread t) {
		this.t = t;
	}
	
	public void run() {
		for(int i = 2;i <= 100;i+=2) {
			System.out.println("###" + i);
			try {
				synchronized (t) {
					t.join();
				}
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

当多线程并发访问临界资源(同一个对象)时,如果破坏了原子操作(不可分割的操作),就会造成数据不一致,这种现象就叫做线程的同步. 例如:用多线程控制栈的push和pop

5.线程池

线程池
①线程池: 线程容器,将预先创建的线程对象存到线程池中,只要将任务提交给线程池,
会分配线程对象完成提交任务,线程池中的线程对象可以被重复使用
②好处: 避免频繁的创建线程和销毁,从而提高空间利用率和执行效率
③线程池常用的接口和类:(位于java.util.concurrent包中)
a.Executor:线程池的顶级接口
b.ExecutorService:是Executor的子接口,线程池的核心接口
(1)submit(Runnable task):将线程任务提交给线程池
(2)shutdown():关闭线程池,将线程池的线程对象全部销毁
c.Executors: 获取线程池对象的工具类,其中方法基本都为静态方法
static ExecutorService newFixedThreadPool(int n):获取一个固定数量线程的线程池
参数指定线程池中线程对象的数量
static ExecutorService newCachedThreadPool():获取动态数量线程对象的线程池,
根据提交的任务需求,不够用时,则自动完成线程创建

Callable
a.Callable接口: 位于java.util.concurrent包中,类似于Runnable接口的应用,对应的对象代表线程任务。
注意: Callable是泛型接口,泛型约束了接口中方法的返回值数据类型
b.接口中的方法: V call(): 带有返回值的方法,同时可以抛出异常
Future f = pool.submit(c1);
c.Future是存储submit提交任务执行之后的返回值
利用Future中的get方法获取执行的结果

6.synchronized

概念及特点:
(1) 任何对象都有一个互斥锁标记,用来分配给线程
(2) 只有拿到对象锁标记的线程,才能进入对该对象加锁的同步代码块
(3) 线程退出同步代码块,会释放相应的锁标记

同步方法:在整个方法的范围内,对当前对象加锁
只有拿到对象锁标记的线程,才能调用该对象的同步方法
锁池:任何对象都有的一个空间,用来存放等待该对象锁标记的线程

注意:一个线程可以同时拥有多个对象的锁标记,当线程阻塞在锁池中时,不会释放其已经拥有的锁标记,由此可能造成死锁

7. Lock

Lock
a.Lock:接口,位于java.util.concurrent.locks包中,代表锁
b.Lock中常用方法:
(1)void lock(): 获取锁
(2)void unlock(): 释放锁
c.实现类: ReentrantLock

8.解决死锁的办法

建立线程间的通信:等待(wait)-通知(notify)
任何对象都有一个等待队列,用来存放线程

线程t1 对o调用wait() 必须放在对o加锁的同步代码块中

效果: (1) t1会释放其拥有的所有锁标记; (2) 同时t1会阻塞在o的等待队列中

线程t2 对o调用notify()/notifyAll()必须放在对o加锁的同步代码块

效果: 从o的等待队列中释放一个/全部线程

package day17hot1;

public class TestWaitNotify {

	public static void main(String[] args) throws Exception {
		Object o = new Object();
		Thread t = new SubThread(o);
		t.start();
		synchronized (o) {
			System.out.println("main1 ...");
			o.wait();
			System.out.println("main2 ...");
		}
	}

}

class SubThread extends Thread {
	Object o;

	public SubThread(Object o) {
		this.o = o;
	}

	@Override
	public void run() {
		synchronized (o) {
			System.out.println("Sub1 ...");
			o.notifyAll();
			System.out.println("Sub2 ...");
		}
	}
}

在这里插入图片描述

9.集合的扩充(CopyOnWriteArrayList)

1.CopyOnWriteArrayList
(1)位于:java.util.concurrent包中
(2)在所有读操作(不会改变集合中数据内容的操作)中不加锁;在写操作时加锁,为了保证数据正确性,
写操作时,拷贝一个副文本,在副文本上进行写操作,写操作完成之后,新数据替换旧数据允许多个
线程同时进行读操作,但是同一时间只允许一个线程进行写操作,同时一个线程进行写操作,也允许
多个线程进行读操作。(牺牲写操作的效率提高读操作的效率)
(3)应用场景: 读操作的次数远远大于写操作次数时
(4)CopyOnWriteArrayList和Vector的共同特点和区别
区别:CopyOnWriteArrayList在读次数远远多于写操作时,效率远高于Vector,仅次于ArrayList
共同点:都是线程安全
CopyOnWriteArrayList和ArrayList
区别:CopyOnWriteArrayList线程安全,ArrayList线程不安全
共同点:用法和ArrayList一样(遍历方式等)

10.面试题: ArrayList和Vector的区别

ArrayList: 所有方法都不是同步方法 可能会造成数据不一致 线程不安全 多线程并发时效率高
Vector: 方法基本上都是同步方法 线程安全 多线程并发时效率低

11.synchronized和其他修饰符的组合

除了abstract不能和synchronized组合,其他的都可以搭配
static和synchronized组合: 表示给当前类对象加锁

注意: synchronized不能修饰构造方法!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值