Java并发编程核心方法与框架-TheadPoolExecutor的使用
类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提供的四种策略。
- AbortPolicy:直接抛出异常。
- CallerRunsPolicy:只用调用者所在线程来运行任务。
- DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。
- DiscardPolicy:不处理,丢弃掉。
当然也可以根据应用场景需要来实现RejectedExecutionHandler接口自定义策略。如记录日志或持久化不能处理的任务。
当提交一个新任务到线程池时,线程池的处理流程如下:
- 线程池判断基本线程池是否已满?没满,创建一个工作线程来执行任务。满了,则进入下个流程。
- 线程池判断工作队列是否已满?没满,则将新提交的任务存储在工作队列里。满了,则进入下个流程。
- 线程池判断整个线程池是否已满?没满,则创建一个新的工作线程来执行任务,满了,则交给饱和策略来处理这个任务。
/*
* 获取基本属性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的使用的更多相关文章
- Java并发编程核心方法与框架-CountDownLatch的使用
Java多线程编程中经常会碰到这样一种场景:某个线程需要等待一个或多个线程操作结束(或达到某种状态)才开始执行.比如裁判员需要等待运动员准备好后才发送开始指令,运动员要等裁判员发送开始指令后才开始比赛 ...
- Java并发编程核心方法与框架-Fork-Join分治编程(一)
在JDK1.7版本中提供了Fork-Join并行执行任务框架,它的主要作用是把大任务分割成若干个小任务,再对每个小任务得到的结果进行汇总,这种开发方法也叫做分治编程,可以极大地利用CPU资源,提高任务 ...
- Java并发编程核心方法与框架-Semaphore的使用
Semaphore中文含义是信号.信号系统,这个类的主要作用就是限制线程并发数量.如果不限制线程并发数量,CPU资源很快就会被耗尽,每个线程执行的任务会相当缓慢,因为CPU要把时间片分配给不同的线程对 ...
- Java并发编程核心方法与框架-CompletionService的使用
接口CompletionService的功能是以异步的方式一边生产新的任务,一边处理已完成任务的结果,这样可以将执行任务与处理任务分离.使用submit()执行任务,使用take取得已完成的任务,并按 ...
- Java并发编程核心方法与框架-ScheduledExecutorService的使用
类SchedukedExecutorService的主要作用是可以将定时任务与线程池功能结合. 使用Callable延迟运行(有返回值) public class MyCallableA implem ...
- Java并发编程核心方法与框架-ExecutorService的使用
在ThreadPoolExecutor中使用ExecutorService中的方法 方法invokeAny()和invokeAll()具有阻塞特性 方法invokeAny()取得第一个完成任务的结果值 ...
- Java并发编程核心方法与框架-Future和Callable的使用
Callable接口与Runnable接口对比的主要优点是Callable接口可以通过Future获取返回值.但是Future接口调用get()方法取得结果时是阻塞的,如果调用Future对象的get ...
- Java并发编程核心方法与框架-Executors的使用
合理利用线程池能够带来三个好处 降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行. 提高线程的可管理性.线程是稀 ...
- Java并发编程核心方法与框架-phaser的使用
arriveAndAwaitAdvance()方法 arriveAndAwaitAdvance()作用是当前线程已经到达屏障,在此等待一段时间,等条件满足后继续向下一个屏障执行. public cla ...
随机推荐
- 强制重启N种方法
强制重启N种方法 2015-12-24 17:19 146人阅读 评论(0) 收藏 举报 本文章已收录于: 分类: 驱动开发学习(458) 作者同类文章X 1. 无意中看到一种通过控制92H端口b ...
- spring spel
•Spring 表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言. •语法类似于 EL:SpEL 使用 #{…} 作为定界符,所有在大框号中的字符都将被认为是 SpE ...
- 面试经验(SG)
(1)给定一个字符串,"hello world high quality",去除里面的字符'h',然后返回一个新的字符串. package niukewang; public cl ...
- 【POJ 3321】Apple Tree
有n个节点以1为根节点的树,给你树的边关系u-v,一开始每个节点都有一个苹果,接下来有两种操作,C x改变节点x的苹果状态,Q x查询x为根的树的所有苹果个数. 求出树的dfs序,st[i]保存i ...
- bzoj4402: Claris的剑
首先,对于本质相同的构造,我们只计算字典序最小的序列 假设序列中最大的元素为top 我们很容易发现这样的序列一定是1,2,..,1,2,3,2,3,...,2,3,4,3,4.........,top ...
- if __name__ == '__main__':
python if __name__ == '__main__': 模块是对象,并且所有的模块都有一个内置属性 __name__.一个模块的 __name__ 的值取决于您如何应用模块.如果 impo ...
- python——复制目录结构小脚本
引言 有个需要,需要把某个目录下的目录结构进行复制,不要文件,当目录结构很少的时候可以手工去建立,当目录结构复杂,目录层次很深,目录很多的时候,这个时候要是还是手动去建立的话,实在不是一种好的方法,弄 ...
- powershell小工具
保存为.ps1文件Set-ExecutionPolicy UnrestrictedSet-ExecutionPolicy Restricted 1. 批量修改文件后缀 $CodeFileDir=&qu ...
- HDU 1548 A strange lift (最短路/Dijkstra)
题目链接: 传送门 A strange lift Time Limit: 1000MS Memory Limit: 32768 K Description There is a strange ...
- linux下git的简单运用
linux下git的简单运用 windows下也有git,是git公司出的bash,基本上模拟了linux下命令行.许多常用的命令和linux下操作一样.也就是说,windows下的git命令操作和l ...