【Java】巧用线程池

线程池

每一个线程的启动和结束都是比较消耗时间和占用资源的。

如果在系统中用到了很多的线程,大量的启动和结束动作会导致系统的性能变卡,响应变慢。

为了解决这个问题,引入线程池这种设计思想。

线程池的模式很像生产者消费者模式,消费的对象是一个一个的能够运行的任务

设计思路

线程池的思路和生产者消费者模型是很接近的。

  1. 准备一个任务容器
  2. 一次性启动10个 消费者线程
  3. 刚开始任务容器是空的,所以线程都wait在上面。
  4. 直到一个外部线程往这个任务容器中扔了一个“任务”,就会有一个消费者线程被唤醒notify
  5. 这个消费者线程取出“任务”,并且执行这个任务,执行完毕后,继续等待下一次任务的到来。
  6. 如果短时间内,有较多的任务加入,那么就会有多个线程被唤醒,去执行这些任务。

在整个过程中,都不需要创建新的线程,而是循环使用这些已经存在的线程。

使用JAVA自带的线程池

创建一个线程池类ThreadPoolExecutor有两种方式,
第一种是用Executors,

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;


private ThreadPoolExecutor executor;//java自带的线程池类;
		
		public Server(){//创建线程池;
			//executor=(ThreadPoolExecutor)Executors.newCachedThreadPool();//不带参数,线程池个数无限
			executor=(ThreadPoolExecutor)Executors.newFixedThreadPool(5);//带参数线程池个数有限;
		}

这种方式创建线程池不推荐,因为会有运行风险,线程个数可能不受控制,下面来介绍第二种

第二种是用ThreadPoolExecutor;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

ThreadPoolExecutor threadPool= new ThreadPoolExecutor(10, 15, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());

第一个参数10 表示这个线程池初始化了10个线程在里面工作
第二个参数15 表示如果10个线程不够用了,就会自动增加到最多15个线程
第三个参数60 结合第四个参数TimeUnit.SECONDS,表示经过60秒,多出来的线程还没有接到活儿,就会回收,最后保持池子里就10个
第四个参数TimeUnit.SECONDS 如上
第五个参数 new LinkedBlockingQueue() 用来放任务的集合

这个方法创建线程池可以使创建的参数更容易理解,还降低程序运行出错的风险,极力推荐,下面放一段代码,是客户端和服务端的例子

线程池类:

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Server {

    ThreadPoolExecutor threadPool= new ThreadPoolExecutor(10, 15, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());

    
          
     
        public void submitTask( Worker worker){   

        threadPool.execute(worker);
  
    }
  

}

任务类:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Worker  implements Runnable{
	Socket s;

	public Worker(Socket s) {
		this.s = s;
	}

	public void run() {
		try {
			System.out.println("服务人员已经启动");
			InputStream ips = s.getInputStream();
			OutputStream ops = s.getOutputStream();
            DataInputStream br=new DataInputStream(ips);
			
			DataOutputStream dos = new DataOutputStream(ops);
			Scanner sc=new Scanner(System.in);
			while (true) {
				String strWord = br.readUTF();
				System.out.println("client said:" + strWord  );
				if (strWord.equalsIgnoreCase("quit"))
					break;
				String str=sc.next();
			
				System.out.println("server said:" + str );
				dos.writeUTF(str  + System.getProperty("line.separator"));
			}
			br.close();
			// 关闭包装类,会自动关闭包装类中所包装的底层类。所以不用调用ips.close()
			dos.close();
			s.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


}

服务端:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {

	public static void main(String[] args) {
		// 创建一个执行服务器
		Server server=new Server();
		try {
			ServerSocket ss=new ServerSocket(8008);
			while(true)
			{
				Socket s=ss.accept();
				System.out.println("来了一个client");
			    Worker worker =new Worker(s);
				server.submitTask(worker);//向线程池提交任务;
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

客户端:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class TcpClient {
	public static void main(String[] args) {
		try {
			Socket s=new Socket(InetAddress.getByName("192.168.1.10"), 8008);
			InputStream ss=s.getInputStream();
			DataInputStream ios=new DataInputStream(ss);
			OutputStream dop =s.getOutputStream();
			DataOutputStream dos=new DataOutputStream(dop);
			Scanner sc=new Scanner(System.in);
			while(true)
			{
				String str=sc.next();
				if(str.equalsIgnoreCase("quit"))
				{
					break;
				}
				else
				{
					
					System.out.println("向客户端发出:"+str);
					dos.writeUTF(str+ System.getProperty("line.separator"));
					String dr=ios.readUTF();
					System.out.println("收到服务端消息:"+dr);
				}
			}
			s.close();
			ss.close();
			dop.close();
			sc.close();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱技术的小小林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值