类ThreadPoolExecutor最常使用的构造方法是

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, unit, BlockingDeque<Runnable> workQueue)
  • corePoolSize 线程池中所保存的线程数,包括空闲线程,也就是核心池的大小。当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。如果调用了线程池的prestartAllCoreThreads方法,线程池会提前创建并启动所有基本线程。
  • maximumPoolSize 池中允许的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。值得注意的是如果使用了无界的任务队列这个参数就没什么效果。
  • keepAliveTime 当线程数量大于corePoolSize值时,在没有超过指定的时间内是不从线程池中将空闲线程删除的。如果超过此时间,则删除。所以如果任务很多,并且每个任务执行的时间比较短,可以调大这个时间,提高线程的利用率。
  • unit keepAliveTime的时间单位
  • workQueue 执行前用于保持任务的队列,此队列仅保持由execute方法提交的Runnable任务

ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按FIFO(先进先出)原则对元素进行排序。

LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO(先进先出)排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。

SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。

PriorityBlockingQueue:一个具有优先级的无限阻塞队列。

其他常用的构造方法参数:

  • ThreadFactory:用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设置更有意义的名字。
  • RejectedExecutionHandler(饱和策略):当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。以下是JDK1.5提供的四种策略。
  1. AbortPolicy:直接抛出异常。
  2. CallerRunsPolicy:只用调用者所在线程来运行任务。
  3. DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。
  4. DiscardPolicy:不处理,丢弃掉。

    当然也可以根据应用场景需要来实现RejectedExecutionHandler接口自定义策略。如记录日志或持久化不能处理的任务。

当提交一个新任务到线程池时,线程池的处理流程如下:

  1. 线程池判断基本线程池是否已满?没满,创建一个工作线程来执行任务。满了,则进入下个流程。
  2. 线程池判断工作队列是否已满?没满,则将新提交的任务存储在工作队列里。满了,则进入下个流程。
  3. 线程池判断整个线程池是否已满?没满,则创建一个新的工作线程来执行任务,满了,则交给饱和策略来处理这个任务。

/*
* 获取基本属性corePoolSize和maximumPoolSize
*/
public class Run {
public static void main(String[] args) {
int corePoolSize = 7;
int maximumPoolSize = 8;
int keepAliveTime = 5;
TimeUnit unit = TimeUnit.SECONDS;
LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
System.out.println(executor.getCorePoolSize());//7
System.out.println(executor.getMaximumPoolSize());//8
System.out.println("---------------------------");
SynchronousQueue<Runnable> synchronousQueue = new SynchronousQueue<>();
executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, synchronousQueue);
System.out.println(executor.getCorePoolSize());//7
System.out.println(executor.getMaximumPoolSize());//8
}
}

如果欲执行的runnable的数量<=corePoolSize,则马上创建线程运行这个任务,并且不放入扩展队列Queue中。

/**
* 队列使用LinkedBlockingDeque类,并且线程数量<=corePoolSize
* 所以keepAliveTime>5时也不清除空闲线程
*/
public class Run2_1 {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = new Runnable() { @Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " run!" + System.currentTimeMillis());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
int corePoolSize = 7;
int maximumPoolSize = 8;
int keepAliveTime = 5;
TimeUnit unit = TimeUnit.SECONDS;
LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<Runnable>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
executor.execute(runnable);//1
executor.execute(runnable);//2
executor.execute(runnable);//3
executor.execute(runnable);//4
executor.execute(runnable);//5
executor.execute(runnable);//6
executor.execute(runnable);//7
Thread.sleep(300);
System.out.println("A:" + executor.getCorePoolSize());//7
System.out.println("A:" + executor.getPoolSize());//7
System.out.println("A:" + executor.getQueue().size());//0
Thread.sleep(10000);
System.out.println("B:" + executor.getCorePoolSize());//7
System.out.println("B:" + executor.getPoolSize());//7
System.out.println("B:" + executor.getQueue().size());//0
}
}

//如果欲执行的runnable的数量<=corePoolSize,则马上创建线程运行这个任务,并且不放入扩展队列Queue中。
/**
* 队列使用SynchronousQueue类,并且线程数量<=corePoolSize
* 所以keepAliveTime>5时也不清除空闲线程
*/
public class Run2_2 {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = new Runnable() { @Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " begin " + System.currentTimeMillis());
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + " end " + System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
};
int corePoolSize = 7;
int maximumPoolSize = 8;
int keepAliveTime = 5;
TimeUnit unit = TimeUnit.SECONDS;
SynchronousQueue<Runnable> workQueue = new SynchronousQueue<>();
// LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
executor.execute(runnable);//1
executor.execute(runnable);//2
executor.execute(runnable);//3
executor.execute(runnable);//4
executor.execute(runnable);//5
executor.execute(runnable);//6
executor.execute(runnable);//7
// TimeUnit.SECONDS.sleep(10);
Thread.sleep(300);
System.out.println("A:" + executor.getCorePoolSize());//7
System.out.println("A:" + executor.getPoolSize());//7
System.out.println("A:" + executor.getQueue().size());//0
TimeUnit.SECONDS.sleep(10);
System.out.println("B:" + executor.getCorePoolSize());//7
System.out.println("B:" + executor.getPoolSize());//7
System.out.println("B:" + executor.getQueue().size());//0
}
}

数量>corePoolSize&&数量<=maxmimumPoolSize的情况

/*
* BlockingQueue是一个接口,常用的实现类有LinkedBlockingQueue和ArrayBlockingQueue.
* LinkedBlockingQueue的好处在于没有大小限制,队列容量非常大,所以执行execute()不会抛出异常
* 线程池中运行的线程的数量永远也不会超过corePoolSize的值,
* 因为多余的线程被放入LinkedBlockingQueue队列中,keepAliveTime参数也就没有意义了。
*/
public class Run3_1 {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = new Runnable() { @Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " run!" + System.currentTimeMillis());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
int corePoolSize = 7;
int maximumPoolSize = 8;
int keepAliveTime = 5;
TimeUnit unit = TimeUnit.SECONDS;
//队列使用LinkedBlockingDeque类,如果线程数量>corePoolSize时将其余的任务放入队列中。
//同一时间最多只能有7个线程执行。
//使用LinkedBlockingDeque类时,maximumPoolSize参数被忽略
LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<Runnable>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
executor.execute(runnable);//1
executor.execute(runnable);//2
executor.execute(runnable);//3
executor.execute(runnable);//4
executor.execute(runnable);//5
executor.execute(runnable);//6
executor.execute(runnable);//7
executor.execute(runnable);//8
//executor.execute(runnable);//8
Thread.sleep(300);
System.out.println("A:" + executor.getCorePoolSize());//7
System.out.println("A:" + executor.getPoolSize());//7
System.out.println("A:" + executor.getQueue().size());//1
Thread.sleep(10000);
System.out.println("B:" + executor.getCorePoolSize());//7
System.out.println("B:" + executor.getPoolSize());//7
System.out.println("B:" + executor.getQueue().size());//0 }
}

以上代码运行结果如下:

pool-1-thread-1 run!1470813110727
pool-1-thread-5 run!1470813110728
pool-1-thread-4 run!1470813110728
pool-1-thread-7 run!1470813110728
pool-1-thread-2 run!1470813110727
pool-1-thread-3 run!1470813110727
pool-1-thread-6 run!1470813110728
A:7
A:7
A:1
pool-1-thread-1 run!1470813111731
B:7
B:7
B:0

可见,线程pool-1-thread-1执行了两个任务。


public class Run3_2 {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = new Runnable() { @Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " run!" + System.currentTimeMillis());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
int corePoolSize = 7;
int maximumPoolSize = 8;
int keepAliveTime = 5;
TimeUnit unit = TimeUnit.SECONDS;
/*
*队列使用SynchronousQueue类并且线程数量>corePoolSize时,将其余的线程放入池中,总数量为8
*并且线程总数量没有超过maximumPoolSize值8
*由于运行线程数为8,数量上>corePoolSize的值7
*所以keepAliveTime>5时清除空闲线程
*如果使用SynchronousQueue类则maximumPoolSize参数的作用将有效
*/
SynchronousQueue<Runnable> workQueue = new SynchronousQueue<Runnable>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
executor.execute(runnable);//1
executor.execute(runnable);//2
executor.execute(runnable);//3
executor.execute(runnable);//4
executor.execute(runnable);//5
executor.execute(runnable);//6
executor.execute(runnable);//7
executor.execute(runnable);//8
//executor.execute(runnable);//8
Thread.sleep(300);
System.out.println("A:" + executor.getCorePoolSize());//7
System.out.println("A:" + executor.getPoolSize());//8
System.out.println("A:" + executor.getQueue().size());//0
Thread.sleep(10000);
System.out.println("B:" + executor.getCorePoolSize());//7
System.out.println("B:" + executor.getPoolSize());//7
System.out.println("B:" + executor.getQueue().size());//0
//删除的是>corePoolSize的多余线程
}
}

以上代码运行结果如下:

pool-1-thread-3 run!1470832826522
pool-1-thread-6 run!1470832826522
pool-1-thread-7 run!1470832826523
pool-1-thread-5 run!1470832826522
pool-1-thread-4 run!1470832826522
pool-1-thread-1 run!1470832826522
pool-1-thread-2 run!1470832826522
pool-1-thread-8 run!1470832826523
A:7
A:8
A:0
B:7
B:7
B:0

数量>maximumPoolSize的情况

public class Run4_1 {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = new Runnable() { @Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " run!" + System.currentTimeMillis());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
int corePoolSize = 7;
int maximumPoolSize = 8;
int keepAliveTime = 5;
TimeUnit unit = TimeUnit.SECONDS;
/*
*队列使用LinkedBlockingDeque类并且线程数量>corePoolSize时,将其余的线程放入池中
*同一时间内只有corePoolSize个线程在运行
*所以keepAliveTime>5时不清除空闲线程
*/
LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<Runnable>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
executor.execute(runnable);//1
executor.execute(runnable);//2
executor.execute(runnable);//3
executor.execute(runnable);//4
executor.execute(runnable);//5
executor.execute(runnable);//6
executor.execute(runnable);//7
executor.execute(runnable);//8
executor.execute(runnable);//9
Thread.sleep(300);
System.out.println("A:" + executor.getCorePoolSize());//7
System.out.println("A:" + executor.getPoolSize());//7
System.out.println("A:" + executor.getQueue().size());//2
Thread.sleep(10000);
System.out.println("B:" + executor.getCorePoolSize());//7
System.out.println("B:" + executor.getPoolSize());//7
System.out.println("B:" + executor.getQueue().size());//0
}
}

运行结果如下:

pool-1-thread-1 run!1470833462484
pool-1-thread-4 run!1470833462484
pool-1-thread-3 run!1470833462484
pool-1-thread-2 run!1470833462484
pool-1-thread-6 run!1470833462484
pool-1-thread-5 run!1470833462484
pool-1-thread-7 run!1470833462485
A:7
A:7
A:2
pool-1-thread-5 run!1470833463489
pool-1-thread-4 run!1470833463489
B:7
B:7
B:0
public class Run4_2 {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = new Runnable() { @Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " run!" + System.currentTimeMillis());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
int corePoolSize = 7;
int maximumPoolSize = 10;
int keepAliveTime = 5;
TimeUnit unit = TimeUnit.SECONDS;
/*
*队列使用SynchronousQueue类并且线程数量>=corePoolSize
*并且线程数量<=maximumPoolSize
*所以keepAliveTime>5时清除空闲线程
*/
SynchronousQueue<Runnable> workQueue = new SynchronousQueue<Runnable>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
executor.execute(runnable);//1
executor.execute(runnable);//2
executor.execute(runnable);//3
executor.execute(runnable);//4
executor.execute(runnable);//5
executor.execute(runnable);//6
executor.execute(runnable);//7
executor.execute(runnable);//8
executor.execute(runnable);//9
Thread.sleep(300);
System.out.println("A:" + executor.getCorePoolSize());//7
System.out.println("A:" + executor.getPoolSize());//9
System.out.println("A:" + executor.getQueue().size());//0
Thread.sleep(10000);
System.out.println("B:" + executor.getCorePoolSize());//7
System.out.println("B:" + executor.getPoolSize());//7
System.out.println("B:" + executor.getQueue().size());//0
}
}

以上代码运行结果如下:

pool-1-thread-2 run!1470833720785
pool-1-thread-5 run!1470833720786
pool-1-thread-4 run!1470833720785
pool-1-thread-3 run!1470833720785
pool-1-thread-1 run!1470833720785
pool-1-thread-6 run!1470833720786
pool-1-thread-7 run!1470833720786
pool-1-thread-8 run!1470833720786
pool-1-thread-9 run!1470833720786
A:7
A:9
A:0
B:7
B:7
B:0
public class Run4_3 {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = new Runnable() { @Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " run!" + System.currentTimeMillis());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
int corePoolSize = 7;
int maximumPoolSize = 8;
int keepAliveTime = 5;
TimeUnit unit = TimeUnit.SECONDS;
/*
*队列使用SynchronousQueue类并且线程数量>corePoolSize
*并且线程数量>maximumPoolSize
*所以出现异常
*/
SynchronousQueue<Runnable> workQueue = new SynchronousQueue<Runnable>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
executor.execute(runnable);//1
executor.execute(runnable);//2
executor.execute(runnable);//3
executor.execute(runnable);//4
executor.execute(runnable);//5
executor.execute(runnable);//6
executor.execute(runnable);//7
executor.execute(runnable);//8
executor.execute(runnable);//9
Thread.sleep(300);
System.out.println("A:" + executor.getCorePoolSize());//
System.out.println("A:" + executor.getPoolSize());//
System.out.println("A:" + executor.getQueue().size());//
Thread.sleep(10000);
System.out.println("B:" + executor.getCorePoolSize());//
System.out.println("B:" + executor.getPoolSize());//
System.out.println("B:" + executor.getQueue().size());//
}
}

运行结果如下:

pool-1-thread-2 run!1470833900655
pool-1-thread-6 run!1470833900655
pool-1-thread-5 run!1470833900655
pool-1-thread-4 run!1470833900655
pool-1-thread-1 run!1470833900655
pool-1-thread-7 run!1470833900656
pool-1-thread-3 run!1470833900655
pool-1-thread-8 run!1470833900656
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.concurrent.chapter4.concurrent07.Run4_3$1@c33f45e rejected from java.util.concurrent.ThreadPoolExecutor@6a754384[Running, pool size = 8, active threads = 8, queued tasks = 0, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372)
at com.concurrent.chapter4.concurrent07.Run4_3.main(Run4_3.java:42)

参数keepAliveTime为0时的实验

public class Run5 {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = new Runnable() { @Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " run!" + System.currentTimeMillis());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
int corePoolSize = 7;
int maximumPoolSize = 10;
int keepAliveTime = 0;
TimeUnit unit = TimeUnit.SECONDS;
/*
*队列使用SynchronousQueue类并且线程数量<corePoolSize
*并且线程数量<=maximumPoolSize
*并且keepAliveTime值为0时 线程执行完毕后立即清除
*/
SynchronousQueue<Runnable> workQueue = new SynchronousQueue<Runnable>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
executor.execute(runnable);//1
executor.execute(runnable);//2
executor.execute(runnable);//3
executor.execute(runnable);//4
executor.execute(runnable);//5
executor.execute(runnable);//6
executor.execute(runnable);//7
executor.execute(runnable);//8
executor.execute(runnable);//9
Thread.sleep(300);
System.out.println("A:" + executor.getCorePoolSize());//7
System.out.println("A:" + executor.getPoolSize());//9
System.out.println("A:" + executor.getQueue().size());//0
Thread.sleep(10000);
System.out.println("B:" + executor.getCorePoolSize());//7
System.out.println("B:" + executor.getPoolSize());//7
System.out.println("B:" + executor.getQueue().size());//0
}
}

运行结果如下:

pool-1-thread-3 run!1470834464969
pool-1-thread-5 run!1470834464969
pool-1-thread-4 run!1470834464969
pool-1-thread-6 run!1470834464969
pool-1-thread-1 run!1470834464969
pool-1-thread-2 run!1470834464969
pool-1-thread-7 run!1470834464970
pool-1-thread-8 run!1470834464970
pool-1-thread-9 run!1470834464970
A:7
A:9
A:0
B:7
B:7
B:0

Java并发编程核心方法与框架-TheadPoolExecutor的使用的更多相关文章

  1. Java并发编程核心方法与框架-CountDownLatch的使用

    Java多线程编程中经常会碰到这样一种场景:某个线程需要等待一个或多个线程操作结束(或达到某种状态)才开始执行.比如裁判员需要等待运动员准备好后才发送开始指令,运动员要等裁判员发送开始指令后才开始比赛 ...

  2. Java并发编程核心方法与框架-Fork-Join分治编程(一)

    在JDK1.7版本中提供了Fork-Join并行执行任务框架,它的主要作用是把大任务分割成若干个小任务,再对每个小任务得到的结果进行汇总,这种开发方法也叫做分治编程,可以极大地利用CPU资源,提高任务 ...

  3. Java并发编程核心方法与框架-Semaphore的使用

    Semaphore中文含义是信号.信号系统,这个类的主要作用就是限制线程并发数量.如果不限制线程并发数量,CPU资源很快就会被耗尽,每个线程执行的任务会相当缓慢,因为CPU要把时间片分配给不同的线程对 ...

  4. Java并发编程核心方法与框架-CompletionService的使用

    接口CompletionService的功能是以异步的方式一边生产新的任务,一边处理已完成任务的结果,这样可以将执行任务与处理任务分离.使用submit()执行任务,使用take取得已完成的任务,并按 ...

  5. Java并发编程核心方法与框架-ScheduledExecutorService的使用

    类SchedukedExecutorService的主要作用是可以将定时任务与线程池功能结合. 使用Callable延迟运行(有返回值) public class MyCallableA implem ...

  6. Java并发编程核心方法与框架-ExecutorService的使用

    在ThreadPoolExecutor中使用ExecutorService中的方法 方法invokeAny()和invokeAll()具有阻塞特性 方法invokeAny()取得第一个完成任务的结果值 ...

  7. Java并发编程核心方法与框架-Future和Callable的使用

    Callable接口与Runnable接口对比的主要优点是Callable接口可以通过Future获取返回值.但是Future接口调用get()方法取得结果时是阻塞的,如果调用Future对象的get ...

  8. Java并发编程核心方法与框架-Executors的使用

    合理利用线程池能够带来三个好处 降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行. 提高线程的可管理性.线程是稀 ...

  9. Java并发编程核心方法与框架-phaser的使用

    arriveAndAwaitAdvance()方法 arriveAndAwaitAdvance()作用是当前线程已经到达屏障,在此等待一段时间,等条件满足后继续向下一个屏障执行. public cla ...

随机推荐

  1. JavaScript动态改变表格单元格内容的方法

    本文实例讲述了JavaScript动态改变表格单元格内容的方法.分享给大家供大家参考.具体如下: JavaScript动态改变表格单元格的内容,下面的代码通过修改单元格的innerHTML来修改单元格 ...

  2. watch监听 chechbox 全选

    // 监控全选checkbox的状态 $scope.$watch('AllCheck', function (newValue, oldValue) { // 第一次不执行 if (newValue ...

  3. [bzoj1854][SCOI2010]游戏

    Description 一个装备有两个属性,一个装备只能被使用一次,一次使用一种属性.攻击boss时需按属性1.属性2.属性3...属性k的顺序使用,问k最大为多少. Input 输入的第一行是一个整 ...

  4. Hibernate学习-在线书城后台管理系统的设计

    写在前面:小编经历了昨天一晚上加今天一整天的“不吃不喝(夸张点…总之就是把时间全分享给TA了)”终于把程序的问题全部解决了,小编现在的心情十分的开森,开森,开森,Happy,话不多说,直接进入正题: ...

  5. 过滤器(Filter)的应用

    过滤器的概念 Java中的Filter 并不是一个标准的Servlet ,它不能处理用户请求,也不能对客户端生成响应. 主要用于对HttpServletRequest 进行预处理,也可以对HttpSe ...

  6. 拉曼软件在win8上运行出错问题

    前提:xp上安装运行都没错  xp的.NET 环境是4.0 ,win8 是64位系统.自带.NET Framework 3 (3.0 3.5) 和.NET Framework 4.51:源程序拷贝到w ...

  7. C#检测驱动是否安装的问题

    #region 检测CCD驱动是否安装成功 string path = @"C:\WINDOWS\system32\drivers\UsbCamIF.sys"; //驱动的默认安装 ...

  8. Linux Command Line Basics

    Most of this note comes from the Beginning the Linux Command Line, Second Edition by Sander van Vugt ...

  9. HDU 5907 Find Q(简单字符串)

    传送门 Description Byteasar is addicted to the English letter 'q'. Now he comes across a string S consi ...

  10. iOS - 落叶加载动画效果

    代码下载地址:https://github.com/nLoser/LeafLoadingView 效果: 说明:效果是在网上看到的,并且自己按照效果自己实现,树叶使用CAEmitterLayer做的, ...