- 多线程
- 基本概念
- Thread类
- 基本使用
- 基本方法
- Runnable接口
- 基本使用
- 比较创建线程两种方式
- Callable接口(jdk 5.0以后)
- 基本使用
- 如何理解Callable接口比Runnable接口强大?
- 线程池(jdk 5.0以后)
- 基本使用
- 简单介绍
- 工作流程
- 好处
- 线程同步
- 基本使用
- 优缺点
- synchronized与lock的对比
- 线程通信
- 生产者消费者问题
- 线程生命周期
进程:是程序的一次执行过程。进程作为资源的分配单位,系统在运行时会给每个进程分配不同的内存区域。
线程:是程序内部的一条执行路径。线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器。
并行:多个cpu同时执行多个任务
并发:一个cpu同时执行多个任务
class Threadone extends Thread{
@Override
public void run() {
for(int i=0;i<=100;i++){
if(i%2==0){
System.out.println("偶数:"+i);
}
}
}
}
class Threadtwo extends Thread{
@Override
public void run() {
for(int i=0;i<=100;i++){
if(i%2!=0){
System.out.println("奇数:"+i);
}
}
}
}
public class MyThread {
public static void main(String[] args) {
Threadone threadone=new Threadone();
Threadtwo threadtwo=new Threadtwo();
threadone.start();
threadtwo.start();
}
}
注意:
1.不能直接调用run()方法启动线程,会使多线程变成单线程。
2.不能让已经start()的线程再执行,不能让进程从死亡状态返回。
start():启动当前线程,调用run()方法。
run():将执行操作声明在此方法中。
currentThread():返回当前执行代码的线程。
getName():获取当前线程名字。
setName():设置当前线程名字。
yield():释放当前cpu执行权。
join():在线程a中调用线程b中的join()。
sleep():让当前线程睡眠指定时间。
getPriority():获取线程优先级。
setPriprity():设置线程优先级。
说明: 只是从概率上讲高优先级高概率获得CPU执行权,并不是一定获得执行权
class Product implements Runnable {
private Goods goods;
public Product(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
while (true){
goods.ProductGoods();
}
}
}
class Consumers implements Runnable{
private Goods goods;
public Consumers(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
while (true){
goods.ComsumerGoods();
}
}
}
public class ProductComsumer {
public static void main(String[] args) {
Goods goods=new Goods();
Product product=new Product(goods);
Consumers comsumer=new Consumers(goods);
Thread thread01=new Thread(product);
Thread thread02=new Thread(comsumer);
thread01.start();
thread02.start();
}
}
比较创建线程两种方式
开发中,优先实现Runnable接口实现方式
原因:
1.实现方式没有类的单继承的局限性。
2.实现方式更适合处理多个线程有共享数据的情况
class Test implements Callable如何理解Callable接口比Runnable接口强大?{ private int sum=0; @Override public Integer call() throws Exception { for (int i=0;i<=100;i++){ System.out.println(i); sum+=i; } return sum; } } public class ThreadCallable { public static void main(String[] args) { Test test=new Test(); FutureTask integerFutureTask = new FutureTask<>(test); Thread thread=new Thread(integerFutureTask); thread.start(); try { Integer sum=integerFutureTask.get(); System.out.println("总和为:"+sum); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
1.call可以有返回值
2.call可以抛出异常,被外面的操作捕获
3.Callable支持泛型
class TestThread implements Runnable{
@Override
public void run() {
for (int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
class TestThread01 implements Runnable{
@Override
public void run() {
for (int i=1000;i>100;i--){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
public class ThreadPool {
public static void main(String[] args) {
ExecutorService executorService= Executors.newFixedThreadPool(100);
TestThread testThread=new TestThread();
TestThread01 testThread01=new TestThread01();
executorService.execute(testThread);
executorService.execute(testThread01);
executorService.shutdown();
}
}
简单介绍
核心线程:线程池新建线程的时候,当前线程总数< corePoolSize,新建的线程即为核心线程。
非核心线程:线程池新建线程的时候,当前线程总数< corePoolSize,新建的线程即为核心线程。
核心线程默认情况下会一直存活在线程池中,即使这个核心线程不工作(空闲状态),除非ThreadPoolExecutor 的 allowCoreThreadTimeOut这个属性为true,那么核心线程如果空闲状态下,超过一定时间后就被销毁。
1.当前线程数量未达到 corePoolSize,则新建一个线程(核心线程)执行任务
2.当前线程数量达到了 corePoolSize,则将任务移入阻塞队列等待,让空闲线程处理;
3.当阻塞队列已满,新建线程(非核心线程)执行任务
4.当阻塞队列已满,总线程数又达到了 maximumPoolSize,就会按照拒绝策略处理无法执行的任务,比如RejectedExecutionHandler抛出异常。
1.减少了创建新线程的时间。
2.重复利用线程池中线程,不需要每次创建。
3.便于线程管理。
class MySynchronized implements Runnable {
private int ticket = 100;
@Override
public void run() {
while (true) {
synchronized (this) {
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket);
ticket--;
} else {
System.out.println(Thread.currentThread().getName() + ":无票了");
break;
}
}
}
}
}
public class Synchronized {
public static void main(String[] args) {
MySynchronized mySynchronized=new MySynchronized();
Thread thread1=new Thread(mySynchronized);
Thread thread2=new Thread(mySynchronized);
Thread thread3=new Thread(mySynchronized);
thread1.setName("窗口1");
thread2.setName("窗口2");
thread3.setName("窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
优缺点
好处:解决了线程的安全问题
缺点:操作同步代码时,只能有一个线程参与,其他线程等待,相当于单线程操作,降低了效率。
1.lock锁(显式锁,需要手动关闭和释放),synchronized(隐式锁,自动释放)
2.lock只有代码块锁,synchronized有代码块锁和方法锁
3.使用lock锁,jvm将花费较少时间调度线程,性能更好。
class Goods{
private int count=0;
public synchronized void ProductGoods() {
if(count<20){
count++;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("生产第"+count+"个产品");
notify();
}
else{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void ComsumerGoods(){
if (count>0){
System.out.println("消费第"+count+"个产品");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
notify();
}
else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Product implements Runnable {
private Goods goods;
public Product(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
while (true){
goods.ProductGoods();
}
}
}
class Consumers implements Runnable{
private Goods goods;
public Consumers(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
while (true){
goods.ComsumerGoods();
}
}
}
public class ProductComsumer {
public static void main(String[] args) {
Goods goods=new Goods();
Product product=new Product(goods);
Consumers comsumer=new Consumers(goods);
Thread thread01=new Thread(product);
Thread thread02=new Thread(comsumer);
thread01.start();
thread02.start();
}
}
线程生命周期



