Java 线程总结

java线程:

概念:

程序是静态代码

进程是程序的一次执行

线程是程序内部的一条执行路径

线程共享同一进程的堆和方法区,但会带来安全的隐患

并行:多个CPU同时执行多个任务,(多个人同时做不同的事)

并行:一个CPU(采用时间片)同时执行多个任务,比如:秒杀、多个人同时做一件事

何时需要多线程

1.需要同时执行多个任务

2.后台运行的程序

3.文件读写

创建多线程的方式一、二

1.创建一个类,继承Thread,重写run方法,在main调用start方法

2.创建一个类实现Runnable接口,将该类作为参数传给Thread

线程的生命周期

1.创建,运行,阻塞,等待,终止

线程安全问题的解决措施

1.1同步代码块解决Runnable线程安全问题

​ synchronized同步监视器(锁){

​ //需要被同步的代码

​ //操作共享数据的代码,即为需要被同步的代码

​ }

同步监视器(锁)的于要求:多个线程必须公用通一 把锁,可以是this

1.2 1.同步代码块解决实现Thread类的安全问题

同步监视器(锁)的于要求:多个线程必须公用通一 把锁,可以是【static】,或者 【类.class】,说明类也是对象

2.1同步方法处理Runnable线程安全问题

如果操作共享数据的代码完整的生命在一个方法中,我们不妨将此方法声明同步的。

同步方法也是有锁的,Runnable的同步监视器是this

2.2同步方法处理继承Thread线程安全问题

但是同步方法必须是静态的,否则默认是this(不唯一),静态使得锁是当前类

单例模式(懒汉模式)

单例:即该类只能生成一个对象

死锁的问题

不同的线程分别占同对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁

解决方法:

专门的算法,原则

尽量减少同步资源的定义

尽量避免嵌套同步

lock锁方式解决线程安全问题

ReentrantLock lock = new RenntrantLock();

try{

lock.lock();

}【catch{

代码块

}】finally{

​ lock.unlock();

}

synchronized 和 lock的不同之处

一个自动一个手动

案例

image-20210323200737106

线程通信

Thead.sleep()

不释放锁

wait()

进入阻塞,释放锁,只能在同步代码快活同步方法(不能再lock中)

notify()

唤醒一个线程

只能在同步代码快活同步方法(不能再lock中)

notifyAll()

唤醒所有进程

只能在同步代码快活同步方法(不能再lock中)

注意:后三个方法的调用者都是同步代码块或同步方法中的监视器,否则会出现异常,他们都定义在Object中

sleep() 和wait() 的异同

同:

1、一旦执行,都可使得当前线程进入阻塞状态

异:

1、方法声明位置不同

2、调用范围不同,sleep方法可以在任何场景下调用,而wait方法只能使用在同步代码块中

3、如果两个方法都是用在同步代码块或同步方法中,sleep不会释放锁,而wait会

多线程创建方式三、四

3.1实现Callable接口

相比run()方法,可以有返回值

可以抛出异常

支持泛型的返回值

需要借助 FutureTask类,比如获取返回结果

FutureTask task = new FutureTask<>(Callable实现类对象);

Object obj = task.get();//抛异常

1、创建Callable的实现类

2、实现call方法,

3、创建Callable接口实现类对象

4、将Callable接口实现类对象作为参数传到FutureTask对象中

5、接收FutureTask对象执行get方法的返回值

3.2使用线程池

经常创建和销毁、使用量特别大的资源,比如并发情况下的线程

思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回去,避免频繁创建销毁,实现重复利用。

好处:

1、提高响应速度

2、降低资源消耗

3、便于线程管理

​ 1.corePoolSize:核心池大小

​ 2.maximumPoolSize:最大线程数

​ 3.keepAliveTime:线程没有任务时最多保持多长时间后会终止。

使用

ThreadPoolExecutor service = (ThreadPoolExecutor ) new Executor.newFixedThreadThreadPoll(10);//10个线程数

使用service来管理线程池

service.execute(Runnable接口实现类对象);//适合Runnable

service.submit(Callable接口实现类对象);//适合Callable,用FutureTask接收,然后get

service.shutdown();//关闭线程池

所以创建多线程有四种方式

posted @ 2021-03-23 21:13  jackandtwo  阅读(47)  评论(0)    收藏  举报