多线程与 线程池
前段时间工作中遇到一个问题,需要开发一个工具 用来 把a数据库中的数据同步到b数据库。
代码是写出来了,跑一次问题还好,但是需要跑一段时间内的数据, 数据量大 ,对方提供的api限制等问题 ,就需要很长的时间的来同步这些数据。
那么怎么来做优化呢----多线程。
实现多线程 通用有2中的写法:继承 thread 类 和 实现runnable 接口 。
(1)继承thread类
public class ExtendsThread extends Thread {
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
}
}
(2)实现runnable接口
public class ImpleRunable implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
}
}
程序中有一串参数必须从 数据库中查询出来后再依次进行任务的执行。实现了多线程后发现一个问题,这些参数每一次请求都是不一样的,那么只好把这些参数全部拿出来,组装成多个任务,利用多线程实现.
下面贴出 据资料 编写的 线程池代码:
package com.bfh.Thread.Pool; import java.util.LinkedList; import com.bfh.Thread.Task.Task; /** * @desc 线程池 * @author bfh * @date 2015-09-27 14:31:51 */ public class MyThreadPool extends ThreadGroup { private boolean isAlive;//线程池是否开启 /** * 如果要支持多线程同步 直接在创建的时候 进行线程同步 * List list = Collections.synchronizedList(new LinkedList(...));*/ private LinkedList taskQueue;//线程池的任务队列 private int threadID;//线程池中的线程Id private static int threadPoolID;//线程池ID /** * 创建新的线程池 numthreads 是线程池中的线程数 * @param name */ public MyThreadPool(int numThreads) { super("ThreadPool-"+(threadPoolID++)); //设置线程池的daemon属性为true 表示线程池中的所有线程被销毁时,线程池会被销毁 super.setDaemon(true); //线程池开启 this. isAlive = true; //新建一个任务队列 this.taskQueue = new LinkedList<>(); //启动numthreads 个线程 for (int i = 0; i < numThreads; i++) { new PooledThread().start(); } } /** * 添加新任务 * @throws IllegalAccessException */ public synchronized void performTask(Task task) throws IllegalAccessException{ if (!this.isAlive) { throw new IllegalAccessException();//线程池被关闭 抛出异常 } if (task != null) { this.taskQueue.add(task); //将任务放到任务队列的尾部 notify();//通知工作线程取任务 } } /** * 获取任务 */ protected synchronized Task getTask() throws InterruptedException { //如果任务列表为空 而线程池没有被关闭 则继续等待任务 while( this.taskQueue.size() == 0 ){ if (!this.isAlive) { return null; } wait(); } return (Task)this.taskQueue.removeFirst(); } /** * 关闭线程池 所有线程停止 不再执行任务 */ public synchronized void close(){ if (isAlive) { this.isAlive = false; this.taskQueue.clear();//清除任务 this.interrupt();//中止线程池中的所有线程 } } /** * 关闭线程池 并等待线程池中的所有任务 运行完成 * 但是不能接收新任务 */ public void join() { //通知其他等待线程 “该线程池 已经关闭” 的消息 synchronized (this) { isAlive = false; notifyAll(); } //等待所有的线程完成 //首先建立一个新的线程组 activecount 方法获取线程池中活动线程的估计数 Thread[] threads = new Thread[this.activeCount()]; //将线程池中 的活动线程拷贝到新创建的线程组 threads 中 int count = this.enumerate(threads); //把此线程组及其子组中的所有活动线程复制到指定数组中。 for (int i = 0; i < count; i++) { try { /** * join(long millis) 等待该线程终止的时间最长为 millis 毫秒 join(long millis, int nanos) 等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。 join() 等待该线程终止。 */ threads[i].join();//等待线程运行结束 } catch (Exception e) { // TODO: handle exception } } } /** * 内部类 用于执行任务的工作线程 * @author Administrator * */ private class PooledThread extends Thread { //构造方法 public PooledThread() { // TODO Auto-generated constructor stub //参数1 代表 该线程所在的线程组对象 即当前线程池对象 //参数2 代表 线程名字 super(MyThreadPool.this,"PooledThread-"+(threadID++)); } @Override public void run() { //如果该线程没有被终止 while(! isInterrupted()){ //获取任务 Task task = null; try { task = getTask(); } catch (InterruptedException e) { } //只要线程池的任务列表不为空 getTask方法就总能得到一个任务 //若getTask()返回null,就表示线程池中已经没有任务,而且线程池已被关闭 if (task == null) { return; } //运行任务 捕捉异常 try { task.preform(); } catch ( Throwable t) { //此处个人理解 为 为了保持线程池 能执行完所有的任务 设置的异常处理机制 //当线程组中的线程有未被捕获的异常发生时 //jvm调用 uncaughtException 方法 uncaughtException(this, t); /** * api 解释如下 * uncaughtException void uncaughtException(Thread t, Throwable e) * 当给定线程因给定的未捕获异常而终止时,调用该方法。 Java 虚拟机将忽略该方法抛出的任何异常。 */ } } } } }
package com.bfh.Thread.Task; public class MyTask implements Task { private int taskID = 0 ;//任务id public MyTask(int taskID) { this.taskID = taskID; } public MyTask() { super(); } @Override public void preform() throws Exception { // TODO Auto-generated method stub System.out.println("mytask "+ taskID+ ":start"); try { // StaticPath. Thread.sleep(1000); } catch (InterruptedException e) { System.out.println(e); } System.out.println("mytask "+ taskID+ ":end"); } }
package com.bfh.Thread.Task; /** * 任务接口类 * @author Administrator * */ public interface Task { /** * * @throws Exception */ public void preform() throws Exception; }
package com.bfh.Thread.Test; import java.util.LinkedList; /** * @desc linkedlist remove(int index) 和 remove() * @author Administrator * */ public class TestLinkedListRemove { public static void main(String[] args) { int index = 2; LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("bfh1"); linkedList.add("bfh2"); linkedList.add("bfh3"); if (index ==1) { linkedList.remove(0); for (String string : linkedList) { System.out.println(string); } } if (index == 2) { linkedList.removeFirst(); for (String string : linkedList) { System.out.println(string); } } } }
package com.bfh.Thread.PoolTest; import com.bfh.Thread.Pool.MyThreadPool; import com.bfh.Thread.Task.MyTask; public class PoolTest { /** * @param args * @throws IllegalAccessException */ public static void main(String[] args) throws IllegalAccessException { // TODO Auto-generated method stub int numThreads = 3;//线程池中的线程数 MyThreadPool myThreadPool = new MyThreadPool(numThreads);//生成线程池 int numTasks = 10;//任务数 //运行任务 for (int i = 0; i < numTasks; i++) { myThreadPool.performTask(new MyTask(i)); } //关闭线程池并等待所有任务完成 myThreadPool.join(); } }
朱雀桥边野草花,乌衣巷口夕阳斜。
旧时王谢堂前燕,飞入寻常百姓家。
浙公网安备 33010602011771号