Java19线程相关优化

线程优化

原因:

1.一个线程占默认先占个1M的运行内存,而线程执行完是等待系统回收的,此时会浪费内存

2.每次使用就创建,运行完等待系统回收,需要频繁创建与回收

3.代码编写冗余

解决:

使用线程池:线程池拥有对线程的创建,回收或复用的容器

1.线程池是可以设置线程上限的

2.会复用线程

3.不会频繁的创建与回收线程

4.不用关心线程怎么创建,只需考虑每个线程执行的任务

线程池的体系结构

顶级接口:Executor

        提供的方法:

 void execute(Runnable command);

作用:执行线程任务,相当于启动线程

子类或子接口:

ExecutorService:

ExecutorService//这是个接口,继承于Executor 下面的都是它的一些方法

    void shutdown();//关闭线程池

    boolean isShutdown();//获取线程池是否关闭,可以看到其返回值为boolean

    Future<?> submit(Runnable task);//提交线程任务,相当于执行线程任务

     <T> Future<T> submit(Callable<T> task);//也是提交线程任务
boolean isTerminated();//判断线程是否执行结束(这是接口)

 

ScheduledExecutorService:调度线程池

ScheduledExecutorService//是个接口 继承于 ExecutorService
是所有调度线程池的父接口
提供的方法:

    schedule(Runnable command,//command线程任务
             long delay, //delay延迟时间
             TimeUnit unit);//unit时间单位
                作用:延迟执行

    schedule(Callable<V> callable,
             long delay, 
             TimeUnit unit);//同上

    scheduleAtFixedRate(Runnable command,//command线程任务
                        long initialDelay,//延迟时间
                        long period,//间隔时间  
                                     **间隔时间=本次任务开始时间-上次任务开始时间
                        TimeUnit unit);//unit时间单位
  作用:延迟重复任务执行,延迟多长时间后执行线程任务,间隔多久再次重复执行线程任务
        如果上次执行任务时间大于间隔时间,那么上次任务执行完毕后再执行本次任务

    scheduleWithFixedDelay(Runnable command,
                           long initialDelay,
                           long delay,//间隔时间
                                      **间隔时间=本次任务开始时间-上次任务结束时间
                           TimeUnit unit);

                       

ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
        这个东西最大的构造函数 7参

5参,6参,7参的了解一下

corePoolSize:核心线程数量,即线程中最少有几个线程
maximumPoolSize:线程池最大线程数量
keepAliveTime:销毁时间,空闲线程多久没有时间被销毁,不会销毁核心线程
unit:时间单位
workQueue:存放线程任务的队列
threadFactory:线程工厂
handler:复用机制与算法

线程池工具类

作用:提供了多种线程池创建的静态方法

类名:Executors

提供的方法:

1.  

 static ExecutorService newCachedThreadPool()

作用:创建一个可变线程池

特点:线程池中线程的数量不固定,根据线程任务的多少进行变化

例:

ExecutorService pool=Executors.newCachedThreadPool();

2.

static ExecutorService newFixedThreadPool(int nThreads)

作用:创建一个固定线程池

参数:线程个数

特点:线程池中线程的数量固定,根据参数(int nThreads)进行变化

例:创建有8个线程的线程池

ExecutorService pool=Executors.newFixedThreadPool(8);

 3.

static ExecutorService newSingleThreadExecutor()

作用:创建一个单线程的线程池

ExecutorService pool1 = Executors.newSingleThreadExecutor();

4.

static ExecutorService newWorkStealingPool()

作用:创建一个抢占线程池(JDK1.8出现)

特点:线程池中的线程都是守护线程,有一个窃取算法

5.

static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

作用:创建一个调度线程池

参数:线程池中的数量

特点:线程任务可以延迟执行

6.

static ScheduledExecutorService newSingleThreadScheduledExecutor()

作用:创建一个单例调度线程池,线程池中的线程只有一个

线程池的使用步骤

1.创建一个线程池

ExecutorService pool=Executors.newFixedThreadPool(3);

2.提交线程任务

使用:

execute(Runnable command)
submit(Runnable task)(建议使用)

还可以使用调度线程池特有的三个方法(
                                                    schedule

                                                    scheduleAtFixedRate

                                                     scheduleWithFixedDelay)

execute:

               1. 只能提交Runnable类型任务

                2.直接抛出执行任务时的异常,可以try cath 捕获

                3.没返回值

submit:

               1.可提交Runnable也可提交Callable类型的任务

                2.会吃掉异常,可用Future的get方法将异常抛出

                3.有返回值

试一试:

ExecutorService pool=Executors.newFixedThreadPool(3);
		
		pool.submit(new Runnable() {		
			@Override
			public void run() {
				System.out.println("使用一下");
			}
		});
		
		pool.execute(new Runnable() {
			
			@Override
			public void run() {
				System.out.println("使用一下2");
			}
		});

 由于没有关闭,可以看到线程一直在运行

3.关闭线程池

线程池对象.shutdown();

	pool.shutdown();

 一般情况下:等线程池中线程执行完任务关闭后关闭,调度线程池特有的方法除外,调度线程池中执行延迟重复任务时,当线程池关闭时,此任务也会关闭

例:

 可以看到上面的例子直接关了

试试:

1个线程打印数字

1个线程打印小写字母

1个线程打印大写字母

package demo1;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Demo2 {
	
	public static void main(String[] args) {
		ExecutorService pool = Executors.newFixedThreadPool(3);
		
		pool.submit(new Runnable() {		
			@Override
			
			public void run() {
				Thread name=Thread.currentThread();	
				for (int i = 1; i <27; i++) {
					System.out.println(name.getName()+" "+i);
				}
			}
		});
		
		pool.submit(new Runnable() {
			
			@Override
			public void run() {
				Thread name=Thread.currentThread();
				for (int i = 97; i <123; i++) {
					System.out.println(name.getName()+" "+(char)i);
				}
			}
		});
		
		pool.submit(new Runnable() {		
			@Override
			public void run() {
				Thread name=Thread.currentThread();
				for (int i = 65; i <91; i++) {
				System.out.println(name.getName()+" "+(char)i);
				}
			}
		});
		
		pool.shutdown();
	}
}

 

线程任务优化

有时需要线程计算一些东西,这就要求线程要有返回值

JDK提供的Callable接口,该接口是有返回值的线程任务

1.创建Callable对象  这是个创建任务的。 而上一个创任务的是 Runnable

Callable 对象名 = new Callable<返回值类型>(){

                @Override

                public 返回值的数据类型 call() throws Exception {

                         return null;

        }

}

2.获取Callable对象的计算结果

                submit方法有返回值,返回值类型为Future型

                Callable的结果可以通过submit返回的Future对象调用get方法

                get方法会阻塞当前线程,直到对应的Callable得到结果

Future<返回数据类型> 对象名2= 线程对象.submit(Callable对象);

返回值数据类型 返回值 = 对象名2.get();

不能配合Thread使用,可以在线程池中使用

试一试:

          一个线程计算1-50的和,一个线程计算101~150的和,获取两个线程运算结果,并正在主线程打印输出

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Test2 {
	public static void main(String[] args) throws InterruptedException, ExecutionException  {
		
		Callable<Integer>c1=new Callable<Integer>() {//创建一个Callable任务
			@Override
			public Integer call() throws Exception {//重写call方法
				int sum=0;
				for (int i = 0; i <51; i++) {
					sum=i+sum;	
				}
				return sum;
			}
		};
		
		ExecutorService pool = Executors.newFixedThreadPool(2);//创个有2个线程的线程池
		
		Future<Integer> f1 = pool.submit(c1);//用Future接收一下
		Future<Integer> f2 = pool.submit(new Callable<Integer>() {//试试用匿名内部类		
			@Override
			public Integer call() throws Exception {
				int sum=0;
				for (int i = 101; i < 151; i++) {					
					sum=i+sum;					
				}			
				return sum;
			}		
		});
		pool.shutdown();
		
		Integer num1 = f1.get();//记得在这抛出异常,抛出方法的异常
		Integer num2 = f2.get();// throws InterruptedException, ExecutionException 
	
		System.out.println(num1+num2);
	
	}
}

锁优化

主要便于使用

体系结构

Lock(接口)

        提供的方法:

                        void lock();关锁

                        void unlock();开锁

synchronized做同步


synchronized (锁对象) {
			
		//代码块
}

效果与Lock做同步相同 

Condition ReentrantLock();创建锁对象
锁对象.lock();

//同步代码块

锁对象.unlock();

      子类:

                ReentrantLock(互斥锁)

                ReadwriteLock(接口)

Condition:锁对象

               提供的方法

                        void await():休眠

                        void signal();唤醒一个        

                           void signal();唤醒所有

ReadwriteLock提供的方法

                Lock readLock():获取一个读锁

                Lock writeLock():获取一个写锁

        注意:

                读-读:异步

                读-写:同步

                写-写:同步

优点:提高了读写的效率

子类: ReentrantReadWriteLock(ReadWriteLock实现类)

例:

ReentrantLock Lock = new ReentrantLock();创建锁对象
while(Number>0) {			
			Lock.lock();			
			if(Number<=0) {
				Lock.unlock();
				return;
			}
			Number--;			
			System.out.println(Thread.currentThread().getName());
				Lock.unlock();			
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值