`
收藏列表
标题 标签 来源
清空表单 jquery 表单 清空
$(':input','#myform')
 .not(':button, :submit, :reset, :hidden')
 .val('')
 .removeAttr('checked')
 .removeAttr('selected');
Log4j配置文件 log4j log4j配置文件,xml格式,分级输出(转)
<?xml version="1.0" encoding="GB2312" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!--#log4j中有5级logger ,#FATAL 0 ,#ERROR 3 ,#WARN 4 ,#INFO 6 ,#DEBUG 7 -->
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>

<!--输出到控制台-->
<!--
<appender name="LOG.Console" class="org.apache.log4j.ConsoleAppender">  
<layout class="org.apache.log4j.PatternLayout">  
  <param name="ConversionPattern" value="%d{yyy-MM-dd HH:mm:ss} [%-5p] %c {%F:%L} - %m%n" />  
</layout>  
</appender>
-->

<!--将级别为DEBUG的信息输出到控制台-->
<appender name="LOG.DEBUG" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="d:/log/debug.log" />
<param name="MaxFileSize" value="5120KB" />
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
  <param name="ConversionPattern" value="%d{yyy-MM-dd HH:mm:ss} [%-5p] %c {%F:%L} - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">  
  <param name="LevelMin" value="DEBUG" />  
  <param name="LevelMax" value="DEBUG" />  
</filter>
</appender>

<!--将级别为INFO的信息输出到控制台-->
<appender name="LOG.INFO" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="d:/log/info.log" />
<param name="MaxFileSize" value="5120KB" />
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
  <param name="ConversionPattern" value="%d{yyy-MM-dd HH:mm:ss} [%-5p] %c {%F:%L} - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">  
  <param name="LevelMin" value="INFO" />  
  <param name="LevelMax" value="INFO" />  
</filter>
</appender>

<!--将级别为WARN的信息输出到控制台-->
<appender name="LOG.WARN" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="d:/log/warn.log" />
<param name="MaxFileSize" value="5120KB" />
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
  <param name="ConversionPattern" value="%d{yyy-MM-dd HH:mm:ss} [%-5p] %c {%F:%L} - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">  
  <param name="LevelMin" value="WARN" />  
  <param name="LevelMax" value="WARN" />  
</filter>
</appender>

<!--将级别为ERROR的信息输出到控制台-->
<appender name="LOG.ERROR" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="d:/log/error.log" />
<param name="MaxFileSize" value="5120KB" />
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
  <param name="ConversionPattern" value="%d{yyy-MM-dd HH:mm:ss} [%-5p] %c {%F:%L} - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">  
  <param name="LevelMin" value="ERROR" />  
  <param name="LevelMax" value="ERROR" />  
</filter>
</appender>

<!--将级别为FATAL的信息输出到控制台-->
<appender name="LOG.FATAL" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="d:/log/fatal.log" />
<param name="MaxFileSize" value="5120KB" />
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
  <param name="ConversionPattern" value="%d{yyy-MM-dd HH:mm:ss} [%-5p] %c {%F:%L} - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">  
  <param name="LevelMin" value="FATAL" />  
  <param name="LevelMax" value="FATAL" />  
</filter>
</appender>

<!--
<appender name="InitAction" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="d:/dbcon.log"/>
<param name="MaxFileSize" value="5120KB"/>
<param name="MaxFileSize" value="10" />
<param name="MaxBackupIndex" value="2" />
<param name="DatePattern" value="'.'yyyy-MM-dd'.'log"/>
<layout class="org.apache.log4j.PatternLayout">
  <param name="ConversionPattern" value="%d{yyy-MM-dd HH:mm:ss} - %m%n"/>
  <param name="ConversionPattern" value="%d{DATE} [%-5p] %c {%F:%L} - %m%n"/>
</layout>
</appender>
-->

<!--设置org.logicalcobwebs包的输出级别为INFO-->
<!--
<category name="org.logicalcobwebs">
<priority value="INFO" />
<appender-ref ref="LOG.Console" />
</category>
-->
<root>
<priority value="DEBUG"/>
<!--
<appender-ref ref="LOG.Console" />
  -->
<appender-ref ref="LOG.DEBUG" />
<appender-ref ref="LOG.INFO" />
<appender-ref ref="LOG.WARN" />
<appender-ref ref="LOG.ERROR" />
<appender-ref ref="LOG.FATAL" />
</root>

</log4j:configuration>
Hbase 增删改查 hbase Java操作Hbase进行建表、删表以及对数据进行增删改查,条件查询
package com.wujintao.hbase.test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.HTablePool;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.FilterList;
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
import org.apache.hadoop.hbase.util.Bytes;

public class JinTaoTest {

	public static Configuration configuration;
	static {
		configuration = HBaseConfiguration.create();
		configuration.set("hbase.zookeeper.property.clientPort", "2181");
		configuration.set("hbase.zookeeper.quorum", "192.168.1.100");
		configuration.set("hbase.master", "192.168.1.100:600000");
	}

	public static void main(String[] args) {
		// createTable("wujintao");
		// insertData("wujintao");
		// QueryAll("wujintao");
		// QueryByCondition1("wujintao");
		// QueryByCondition2("wujintao");
		//QueryByCondition3("wujintao");
		//deleteRow("wujintao","abcdef");
		deleteByCondition("wujintao","abcdef");
	}

	/**
	 * 创建表
	 * @param tableName
	 */
	public static void createTable(String tableName) {
		System.out.println("start create table ......");
		try {
			HBaseAdmin hBaseAdmin = new HBaseAdmin(configuration);
			if (hBaseAdmin.tableExists(tableName)) {// 如果存在要创建的表,那么先删除,再创建
				hBaseAdmin.disableTable(tableName);
				hBaseAdmin.deleteTable(tableName);
				System.out.println(tableName + " is exist,detele....");
			}
			HTableDescriptor tableDescriptor = new HTableDescriptor(tableName);
			tableDescriptor.addFamily(new HColumnDescriptor("column1"));
			tableDescriptor.addFamily(new HColumnDescriptor("column2"));
			tableDescriptor.addFamily(new HColumnDescriptor("column3"));
			hBaseAdmin.createTable(tableDescriptor);
		} catch (MasterNotRunningException e) {
			e.printStackTrace();
		} catch (ZooKeeperConnectionException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("end create table ......");
	}

	/**
	 * 插入数据
	 * @param tableName
	 */
	public static void insertData(String tableName) {
		System.out.println("start insert data ......");
		HTablePool pool = new HTablePool(configuration, 1000);
		HTable table = (HTable) pool.getTable(tableName);
		Put put = new Put("112233bbbcccc".getBytes());// 一个PUT代表一行数据,再NEW一个PUT表示第二行数据,每行一个唯一的ROWKEY,此处rowkey为put构造方法中传入的值
		put.add("column1".getBytes(), null, "aaa".getBytes());// 本行数据的第一列
		put.add("column2".getBytes(), null, "bbb".getBytes());// 本行数据的第三列
		put.add("column3".getBytes(), null, "ccc".getBytes());// 本行数据的第三列
		try {
			table.put(put);
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("end insert data ......");
	}

	/**
	 * 删除一张表
	 * @param tableName
	 */
	public static void dropTable(String tableName) {
		try {
			HBaseAdmin admin = new HBaseAdmin(configuration);
			admin.disableTable(tableName);
			admin.deleteTable(tableName);
		} catch (MasterNotRunningException e) {
			e.printStackTrace();
		} catch (ZooKeeperConnectionException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
	/**
	 * 根据 rowkey删除一条记录
	 * @param tablename
	 * @param rowkey
	 */
	 public static void deleteRow(String tablename, String rowkey)  {
		try {
			HTable table = new HTable(configuration, tablename);
			List list = new ArrayList();
			Delete d1 = new Delete(rowkey.getBytes());
			list.add(d1);
			
			table.delete(list);
			System.out.println("删除行成功!");
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		

	}

	 /**
	  * 组合条件删除
	  * @param tablename
	  * @param rowkey
	  */
	 public static void deleteByCondition(String tablename, String rowkey)  {
			//目前还没有发现有效的API能够实现 根据非rowkey的条件删除 这个功能能,还有清空表全部数据的API操作

	}


	/**
	 * 查询所有数据
	 * @param tableName
	 */
	public static void QueryAll(String tableName) {
		HTablePool pool = new HTablePool(configuration, 1000);
		HTable table = (HTable) pool.getTable(tableName);
		try {
			ResultScanner rs = table.getScanner(new Scan());
			for (Result r : rs) {
				System.out.println("获得到rowkey:" + new String(r.getRow()));
				for (KeyValue keyValue : r.raw()) {
					System.out.println("列:" + new String(keyValue.getFamily())
							+ "====值:" + new String(keyValue.getValue()));
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 单条件查询,根据rowkey查询唯一一条记录
	 * @param tableName
	 */
	public static void QueryByCondition1(String tableName) {

		HTablePool pool = new HTablePool(configuration, 1000);
		HTable table = (HTable) pool.getTable(tableName);
		try {
			Get scan = new Get("abcdef".getBytes());// 根据rowkey查询
			Result r = table.get(scan);
			System.out.println("获得到rowkey:" + new String(r.getRow()));
			for (KeyValue keyValue : r.raw()) {
				System.out.println("列:" + new String(keyValue.getFamily())
						+ "====值:" + new String(keyValue.getValue()));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 单条件按查询,查询多条记录
	 * @param tableName
	 */
	public static void QueryByCondition2(String tableName) {

		try {
			HTablePool pool = new HTablePool(configuration, 1000);
			HTable table = (HTable) pool.getTable(tableName);
			Filter filter = new SingleColumnValueFilter(Bytes
					.toBytes("column1"), null, CompareOp.EQUAL, Bytes
					.toBytes("aaa")); // 当列column1的值为aaa时进行查询
			Scan s = new Scan();
			s.setFilter(filter);
			ResultScanner rs = table.getScanner(s);
			for (Result r : rs) {
				System.out.println("获得到rowkey:" + new String(r.getRow()));
				for (KeyValue keyValue : r.raw()) {
					System.out.println("列:" + new String(keyValue.getFamily())
							+ "====值:" + new String(keyValue.getValue()));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * 组合条件查询
	 * @param tableName
	 */
	public static void QueryByCondition3(String tableName) {

		try {
			HTablePool pool = new HTablePool(configuration, 1000);
			HTable table = (HTable) pool.getTable(tableName);

			List<Filter> filters = new ArrayList<Filter>();

			Filter filter1 = new SingleColumnValueFilter(Bytes
					.toBytes("column1"), null, CompareOp.EQUAL, Bytes
					.toBytes("aaa"));
			filters.add(filter1);

			Filter filter2 = new SingleColumnValueFilter(Bytes
					.toBytes("column2"), null, CompareOp.EQUAL, Bytes
					.toBytes("bbb"));
			filters.add(filter2);

			Filter filter3 = new SingleColumnValueFilter(Bytes
					.toBytes("column3"), null, CompareOp.EQUAL, Bytes
					.toBytes("ccc"));
			filters.add(filter3);

			FilterList filterList1 = new FilterList(filters);

			Scan scan = new Scan();
			scan.setFilter(filterList1);
			ResultScanner rs = table.getScanner(scan);
			for (Result r : rs) {
				System.out.println("获得到rowkey:" + new String(r.getRow()));
				for (KeyValue keyValue : r.raw()) {
					System.out.println("列:" + new String(keyValue.getFamily())
							+ "====值:" + new String(keyValue.getValue()));
				}
			}
			rs.close();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
可以通过命令关闭的Socket服务器程序 多线程, 网络通信 孙卫琴 :<<Java网络编程精解>>
//可以监听关闭命令的服务器
package multithread4;
import java.io.*;
import java.net.*;
import java.util.concurrent.*;

public class EchoServer {
  private int port=8000;
  private ServerSocket serverSocket;
  private ExecutorService executorService; //线程池
  private final int POOL_SIZE=4;  //单个CPU时线程池中工作线程的数目
  
  private int portForShutdown=8001;  //用于监听关闭服务器命令的端口
  private ServerSocket serverSocketForShutdown;
  private boolean isShutdown=false; //服务器是否已经关闭

  private Thread shutdownThread=new Thread(){   //负责关闭服务器的线程
    public void start(){
      this.setDaemon(true);  //设置为守护线程(也称为后台线程)
      super.start();
    }

    public void run(){
      while (!isShutdown) {
        Socket socketForShutdown=null;
        try {
          socketForShutdown= serverSocketForShutdown.accept();
          BufferedReader br = new BufferedReader(
                            new InputStreamReader(socketForShutdown.getInputStream()));
          String command=br.readLine();
         if(command.equals("shutdown")){
            long beginTime=System.currentTimeMillis(); 
            socketForShutdown.getOutputStream().write("服务器正在关闭\r\n".getBytes());
            isShutdown=true;
            //请求关闭线程池
//线程池不再接收新的任务,但是会继续执行完工作队列中现有的任务
            executorService.shutdown();  
            
            //等待关闭线程池,每次等待的超时时间为30秒
            while(!executorService.isTerminated())
              executorService.awaitTermination(30,TimeUnit.SECONDS); 
            
            serverSocket.close(); //关闭与EchoClient客户通信的ServerSocket 
            long endTime=System.currentTimeMillis(); 
            socketForShutdown.getOutputStream().write(("服务器已经关闭,"+
                "关闭服务器用了"+(endTime-beginTime)+"毫秒\r\n").getBytes());
            socketForShutdown.close();
            serverSocketForShutdown.close();
            
          }else{
            socketForShutdown.getOutputStream().write("错误的命令\r\n".getBytes());
            socketForShutdown.close();
          }  
        }catch (Exception e) {
           e.printStackTrace();
        } 
      } 
    }
  };

  public EchoServer() throws IOException {
    serverSocket = new ServerSocket(port);
    serverSocket.setSoTimeout(60000); //设定等待客户连接的超过时间为60秒
    serverSocketForShutdown = new ServerSocket(portForShutdown);

    //创建线程池
    executorService= Executors.newFixedThreadPool( 
	    Runtime.getRuntime().availableProcessors() * POOL_SIZE);
    
    shutdownThread.start(); //启动负责关闭服务器的线程
    System.out.println("服务器启动");
  }
  
  public void service() {
    while (!isShutdown) {
      Socket socket=null;
      try {
        socket = serverSocket.accept();  //可能会抛出SocketTimeoutException和SocketException
        socket.setSoTimeout(60000);  //把等待客户发送数据的超时时间设为60秒          
        executorService.execute(new Handler(socket));  //可能会抛出RejectedExecutionException
      }catch(SocketTimeoutException e){
         //不必处理等待客户连接时出现的超时异常
      }catch(RejectedExecutionException e){
         try{
           if(socket!=null)socket.close();
         }catch(IOException x){}
         return;
      }catch(SocketException e) {
         //如果是由于在执行serverSocket.accept()方法时,
         //ServerSocket被ShutdownThread线程关闭而导致的异常,就退出service()方法
         if(e.getMessage().indexOf("socket closed")!=-1)return;
       }catch(IOException e) {
         e.printStackTrace();
      }
    }
  }

  public static void main(String args[])throws IOException {
    new EchoServer().service();
  }
}
class Handler implements Runnable{
  private Socket socket;
  public Handler(Socket socket){
    this.socket=socket;
  }
  private PrintWriter getWriter(Socket socket)throws IOException{
    OutputStream socketOut = socket.getOutputStream();
    return new PrintWriter(socketOut,true);
  }
  private BufferedReader getReader(Socket socket)throws IOException{
    InputStream socketIn = socket.getInputStream();
    return new BufferedReader(new InputStreamReader(socketIn));
  }
  public String echo(String msg) {
    return "echo:" + msg;
  }
  public void run(){
    try {
      System.out.println("New connection accepted " +
      socket.getInetAddress() + ":" +socket.getPort());
      BufferedReader br =getReader(socket);
      PrintWriter pw = getWriter(socket);

      String msg = null;
      while ((msg = br.readLine()) != null) {
        System.out.println(msg);
        pw.println(echo(msg));
        if (msg.equals("bye"))
          break;
      }
    }catch (IOException e) {
       e.printStackTrace();
    }finally {
       try{
         if(socket!=null)socket.close();
       }catch (IOException e) {e.printStackTrace();}
    }
  }
}
//发出关闭服务器命令的程序
package multithread4;
import java.net.*;
import java.io.*;
public class AdminClient{
  public static void main(String args[]){
    Socket socket=null;
    try{
      socket=new Socket("localhost",8001);
      //发送关闭命令
      OutputStream socketOut=socket.getOutputStream();
      socketOut.write("shutdown\r\n".getBytes());
 
      //接收服务器的反馈
      BufferedReader br = new BufferedReader(
                                  new InputStreamReader(socket.getInputStream()));
      String msg=null;
      while((msg=br.readLine())!=null)
        System.out.println(msg);
    }catch(IOException e){
      e.printStackTrace();
    }finally{
      try{
        if(socket!=null)socket.close();
      }catch(IOException e){e.printStackTrace();}
    }
  }
}
使用JDK库提供的线程池实现的服务器 多线程, 网络通信 孙卫琴:<<Java网络编程精解>>
package multithread3;
import java.io.*;
import java.net.*;
import java.util.concurrent.*;

public class EchoServer {
  private int port=8000;
  private ServerSocket serverSocket;
  private ExecutorService executorService;  //线程池
  private final int POOL_SIZE=4;  //单个CPU时线程池中工作线程的数目

  public EchoServer() throws IOException {
    serverSocket = new ServerSocket(port);
    //创建线程池
    //Runtime的availableProcessors()方法返回当前系统的CPU的数目
    //系统的CPU越多,线程池中工作线程的数目也越多 
    executorService= Executors.newFixedThreadPool( 
	    Runtime.getRuntime().availableProcessors() * POOL_SIZE);

    System.out.println("服务器启动");
  }

  public void service() {
    while (true) {
      Socket socket=null;
      try {
        socket = serverSocket.accept();
        executorService.execute(new Handler(socket));
      }catch (IOException e) {
         e.printStackTrace();
      }
    }
  }

  public static void main(String args[])throws IOException {
    new EchoServer().service();
  }
}

class Handler implements Runnable{
  private Socket socket;
  public Handler(Socket socket){
    this.socket=socket;
  }
  private PrintWriter getWriter(Socket socket)throws IOException{
    OutputStream socketOut = socket.getOutputStream();
    return new PrintWriter(socketOut,true);
  }
  private BufferedReader getReader(Socket socket)throws IOException{
    InputStream socketIn = socket.getInputStream();
    return new BufferedReader(new InputStreamReader(socketIn));
  }
  public String echo(String msg) {
    return "echo:" + msg;
  }
  public void run(){
    try {
      System.out.println("New connection accepted " +
      socket.getInetAddress() + ":" +socket.getPort());
      BufferedReader br =getReader(socket);
      PrintWriter pw = getWriter(socket);

      String msg = null;
      while ((msg = br.readLine()) != null) {
        System.out.println(msg);
        pw.println(echo(msg));
        if (msg.equals("bye"))
          break;
      }
    }catch (IOException e) {
       e.printStackTrace();
    }finally {
       try{
         if(socket!=null)socket.close();
       }catch (IOException e) {e.printStackTrace();}
    }
  }
}
自定义的线程池代码 多线程 孙卫琴的代码
//使用线程池的服务器类
package multithread2;
import java.io.*;
import java.net.*;
public class EchoServer {
  private int port=8000;
  private ServerSocket serverSocket;
  private ThreadPool threadPool;  //线程池
  private final int POOL_SIZE=4;  //单个CPU时线程池中工作线程的数目

  public EchoServer() throws IOException {
    serverSocket = new ServerSocket(port);
    //创建线程池
    //Runtime的availableProcessors()方法返回当前系统的CPU的数目
    //系统的CPU越多,线程池中工作线程的数目也越多 
    threadPool= new ThreadPool( 
            Runtime.getRuntime().availableProcessors() * POOL_SIZE);

    System.out.println("服务器启动");
  }

  public void service() {
    while (true) {
      Socket socket=null;
      try {
        socket = serverSocket.accept();
        threadPool.execute(new Handler(socket)); //把与客户通信的任务交给线程池
      }catch (IOException e) {
         e.printStackTrace();
      }
    }
  }

  public static void main(String args[])throws IOException {
    new EchoServer().service();
  }
}

class Handler implements Runnable{
  private Socket socket;
  public Handler(Socket socket){
    this.socket=socket;
  }
  private PrintWriter getWriter(Socket socket)throws IOException{
    OutputStream socketOut = socket.getOutputStream();
    return new PrintWriter(socketOut,true);
  }
  private BufferedReader getReader(Socket socket)throws IOException{
    InputStream socketIn = socket.getInputStream();
    return new BufferedReader(new InputStreamReader(socketIn));
  }
  public String echo(String msg) {
    return "echo:" + msg;
  }
  public void run(){
    try {
      System.out.println("New connection accepted " +
      socket.getInetAddress() + ":" +socket.getPort());
      BufferedReader br =getReader(socket);
      PrintWriter pw = getWriter(socket);

      String msg = null;
      while ((msg = br.readLine()) != null) {
        System.out.println(msg);
        pw.println(echo(msg));
        if (msg.equals("bye"))
          break;
      }
    }catch (IOException e) {
       e.printStackTrace();
    }finally {
       try{
         if(socket!=null)socket.close();
       }catch (IOException e) {e.printStackTrace();}
    }
  }
}

//线程池类
package multithread2;
import java.util.LinkedList;

//线程组表示一个线程的集合。此外,线程组也可以包含其他线程组。线程组构成一棵树,在树中,除了初始线程组外,每个线程组都有一个父线程组。 
//允许线程访问有关自己的线程组的信息,但是不允许它访问有关其线程组的父线程组或其他任何线程组的信息。 
public class ThreadPool extends ThreadGroup {
	private boolean isClosed=false;  //线程池是否关闭
	private LinkedList<Runnable> workQueue;  //表示工作队列,线程结构是非安全的,需要外同步,具体可以参考JDK文档。对象的值保持同步
	private static int threadPoolID;  //表示线程池ID
	private int threadID;  //表示工作线程ID

	public ThreadPool(int poolSize) { //poolSize指定线程池中的工作线程数目
		super("ThreadPool-" + (threadPoolID++));
		setDaemon(true);							//线程池默认设为守护线程
		workQueue = new LinkedList<Runnable>();  //创建工作队列
		//workQueue = Collections.synchronizedList(new LinkedList(...)); //为了避免不同步访问的问题,应该做如下包装。

		for (int i=0; i<poolSize; i++)
		{
			new WorkThread().start();  //创建并启动工作线程
		}

	}

	/** 向工作队列中加入一个新任务,由工作线程去执行该任务 */
	public synchronized void execute(Runnable task) {
		if (isClosed) { //线程池被关则抛出IllegalStateException异常
			throw new IllegalStateException();
		}
		if (task != null) {
			workQueue.add(task);
			notify();  //唤醒正在getTask()方法中等待任务的工作线程
		}
	}

	/** 从工作队列中取出一个任务,工作线程会调用此方法 */
	protected synchronized Runnable getTask()throws InterruptedException{
		while (workQueue.size() == 0) {
			if (isClosed) return null;
			wait();  //如果工作队列中没有任务,就等待任务
		}
		return workQueue.removeFirst();
	}

	//可以根据自己的需求,灵活选择join或是close的方式

	/** 关闭线程池 */
	public synchronized void close() {
		if (!isClosed) {
			isClosed = true;
			workQueue.clear(); //清空工作队列
			interrupt();  //中断所有的工作线程,该方法继承自ThreadGroup类
		}
	}

	/** 等待工作线程把所有任务执行完 */
	public void join() {
		synchronized (this) {
			isClosed = true;
			notifyAll();  //唤醒还在getTask()方法中等待任务的工作线程
		}

		Thread[] threads = new Thread[activeCount()];
		//enumerate()方法继承自ThreadGroup类,获得线程组中当前所有活着的工作线程
		int count = enumerate(threads);  
		for (int i=0; i<count; i++) { //等待所有工作线程运行结束
			try {
				threads[i].join();  //等待工作线程运行结束
			}catch(InterruptedException ex) { }
		}
	}

	/**  内部类:工作线程  */
	private class WorkThread extends Thread {
		public WorkThread() {
			//加入到当前ThreadPool线程组中
			super(ThreadPool.this,"WorkThread-" + (threadID++));
		}

		public void run() {
			while (!isInterrupted()) {  //isInterrupted()方法继承自Thread类,判断线程是否被中断
				Runnable task = null;
				try { //得到任务
					task = getTask();
				}catch (InterruptedException ex){}

				// 如果getTask()返回null或者线程执行getTask()时被中断,则结束此线程
				if (task == null) return;

				try { //运行任务,捕获异常
					task.run();
				} catch (Throwable t) {
					t.printStackTrace();
				}
			}//#while
		}//#run()
	}//#WorkThread类
}
//线程池测试类
package multithread2;
public class ThreadPoolTester {
	public static void main(String[] args) {
		/**程序测试的项:
		 * 1.进程数小于线程池的大小,线程池的效果才会展现出来。
		 * 2.线程池的join和close的区别。从打印信息来看,效果很明显。
		 * */
//		args = new String[2];
//		args[0] = "10";
//		args[1] = "5";
		if (args.length != 2) {
			System.out.println(
					"用法: java ThreadPoolTest numTasks poolSize");
			System.out.println(
			"  numTasks - integer: 任务的数目");
			System.out.println(
			"  numThreads - integer: 线程池中的线程数目");
			return;
		}
		int numTasks = Integer.parseInt(args[0]);
		int poolSize = Integer.parseInt(args[1]);

		ThreadPool threadPool = new ThreadPool(poolSize);  //创建线程池

		// 运行任务
		for (int i=0; i<numTasks; i++)
			threadPool.execute(createTask(i));

		threadPool.join();  //等待工作线程完成所有的任务
		//threadPool.close(); //关闭线程池
	}//#main()

	/**  定义了一个简单的任务(打印ID)   */
	private static Runnable createTask(final int taskID) {
		return new Runnable() {
			public void run() {
				System.out.println("Task " + taskID + ": start");
				try {
					Thread.sleep(500);  //增加执行一个任务的时间
				} catch (InterruptedException ex) { }
				System.out.println("Task " + taskID + ": end");
			}
		};
	}
}

Global site tag (gtag.js) - Google Analytics