㈠ java future函数的作用
在并发编程时,一般使用runnable,然后扔给线程池完事,这种情况下不需要线程的结果。
所以run的返回值是void类型。
如果是一个多线程协作程序,比如菲波拉切数列,1,1,2,3,5,8...使用多线程来计算。
但后者需要前者的结果,就需要用callable接口了。
callable用法和runnable一样,信袜只不过调用的是call方法,该方法有一个泛型返回值类型,你可以任意指定。
线程是帆坦薯属于异步计算模型,所以你不可能直接从别的线程中得到函数返回值。
这时候,Future就出场了。Futrue可以监视目标线程调用call的情况,当你调用Future的get()方法以获得结果时,当前线态者程就开始阻塞,直接call方法结束返回结果。
㈡ ExecutorService中submit和execute的区别
ExecutorService中submit和execute的区别有三点:
1、接收的参数不同
2、submit有返回值,而execute没有
用到返回值的例子,比如说应用中有很多个做validation的task,用户希望所有的task执行完,然后每个task告诉主程序执行结果,是成功还是失败,如果是失败拦闹,原因是什么。然后就可以把所有失败的原因综合起来发给调用者。
3、submit方便Exception处理,而execute处理异常比较麻烦。
在task里会抛出checked或者unchecked exception,而用户又希望外面的调用者能够感知这些exception并做出及时的处理,那么就需要用到submit,通过捕获Future.get抛出的异常。
举例说明:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ExecutorServiceTest {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<String>> resultList = new ArrayList<Future<String>>();
// 创建10个任务并执行
for (int i = 0; i < 10; i++) {
// 使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
Future<String> future = executorService.submit(new TaskWithResult(i));
// 将任务执行结果歼罩存储到List中
resultList.add(future);
}
executorService.shutdown();
// 遍历任务的结果
for (Future<String> fs : resultList) {
try {
System.out.println(fs.get()); // 打印各个线程(任务)执行的结简改罩果
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
executorService.shutdownNow();
e.printStackTrace();
return;
}
}
}
}
class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) {
this.id = id;
}
/**
* 任务的具体过程,一旦任务传给ExecutorService的submit方法,则该方法自动在一个线程上执行。
*
* @return
* @throws Exception
*/
public String call() throws Exception {
System.out.println("call()方法被自动调用,干活!!! " + Thread.currentThread().getName());
if (new Random().nextBoolean())
throw new TaskException("Meet error in task." + Thread.currentThread().getName());
// 一个模拟耗时的操作
for (int i = 999999999; i > 0; i--)
;
return "call()方法被自动调用,任务的结果是:" + id + " " + Thread.currentThread().getName();
}
}
class TaskException extends Exception {
public TaskException(String message) {
super(message);
}
}
执行的结果类似于:
call()方法被自动调用,干活!!! pool-1-thread-1
call()方法被自动调用,干活!!! pool-1-thread-2
call()方法被自动调用,干活!!! pool-1-thread-3
call()方法被自动调用,干活!!! pool-1-thread-5
call()方法被自动调用,干活!!! pool-1-thread-7
call()方法被自动调用,干活!!! pool-1-thread-4
call()方法被自动调用,干活!!! pool-1-thread-6
call()方法被自动调用,干活!!! pool-1-thread-7
call()方法被自动调用,干活!!! pool-1-thread-5
call()方法被自动调用,干活!!! pool-1-thread-8
call()方法被自动调用,任务的结果是:0 pool-1-thread-1
call()方法被自动调用,任务的结果是:1 pool-1-thread-2
java.util.concurrent.ExecutionException: com.cicc.pts.TaskException: Meet error in task.pool-1-thread-3
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
at java.util.concurrent.FutureTask.get(FutureTask.java:83)
at com.cicc.pts.ExecutorServiceTest.main(ExecutorServiceTest.java:29)
Caused by: com.cicc.pts.TaskException: Meet error in task.pool-1-thread-3
at com.cicc.pts.TaskWithResult.call(ExecutorServiceTest.java:57)
at com.cicc.pts.TaskWithResult.call(ExecutorServiceTest.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
㈢ Java多线程是什么意思
1、继承Thread类实现多线程
继承Thread类的方法尽管被我列为一种多线程实现方式,但Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。例如:
代码说明:
上述代码中Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
public static ExecutorService newFixedThreadPool(int nThreads)
创建固定数目线程的线程池。
public static ExecutorService newCachedThreadPool()
创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
public static ExecutorService newSingleThreadExecutor()
创建一个单线程化的Executor。
public static ScheledExecutorService newScheledThreadPool(int corePoolSize)
创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
总结:ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。
㈣ java项目中很多地方使用线程池,线上服务器内存占用越来越大.每个线程占用8.8M.问题是哪儿
针对你说的这种情况,可以使用jvisualvm.exe直接查看内存使用情况,查看是否是有大对象。
㈤ java并发包有哪些类
1、
一个同步辅助类,允许一组线程相互等待,直到这组线程都到达某个公共屏障点。该barrier在释放等待线程后可以重用,因此称为循环的barrier。
来个示例:
[java]view plain
packagetest;
importjava.util.concurrent.CyclicBarrier;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
publicclassRecipes_CyclicBarrier{
=newCyclicBarrier(10);
publicstaticvoidmain(String[]args){
ExecutorServiceexecutor=Executors.newCachedThreadPool();//FixedThreadPool(10);
for(inti=1;i<=10;i++){
executor.submit(newThread(newRunner(i+"号选手")));
}
executor.shutdown();
}
}
classRunnerimplementsRunnable{
privateStringname;
publicRunner(Stringname){
this.name=name;
}
@Override
publicvoidrun(){
System.out.println(name+"准备好了。");
try{
Recipes_CyclicBarrier.barrier.await();//此处就是公共屏障点,所有线程到达之后,会释放所有等待的线程
}catch(Exceptione){
}
System.out.println(name+"起跑!");
}
}
2、CountDownLatch
CountDownLatch和CyclicBarrier有点类似,但是还是有些区别的。CountDownLatch也是一个同步辅助类,它允许一个或者多个线程一直等待,直到正在其他线程中执行的操作完成。它是等待正在其他线程中执行的操作,并不是线程之间相互等待。CountDownLatch初始化时需要给定一个计数值,每个线程执行完之后,必须调用countDown()方法使计数值减1,直到计数值为0,此时等待的线程才会释放。
来个示例:
[java]view plain
packagetest;
importjava.util.concurrent.CountDownLatch;
importjava.util.concurrent.CyclicBarrier;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
publicclassCountDownLatchDemo{
=newCountDownLatch(10);//初始化计数值
publicstaticvoidmain(String[]args){
ExecutorServiceexecutor=Executors.newCachedThreadPool();//FixedThreadPool(10);
for(inti=1;i<=10;i++){
executor.submit(newThread(newRunner1(i+"号选手")));
}
executor.shutdown();
}
}
{
privateStringname;
publicRunner1(Stringname){
this.name=name;
}
@Override
publicvoidrun(){
System.out.println(name+"准备好了。");
CountDownLatchDemo.countDownLatch.countDown();//计数值减1
try{
CountDownLatchDemo.countDownLatch.await();
}catch(Exceptione){
}
System.out.println(name+"起跑!");
}
}
3、CopyOnWriteArrayList & CopyOnWriteArraySet
CopyOnWriteArrayList & CopyOnWriteArraySet是并发容器,适合读多写少的场景,如网站的黑白名单设置。缺点是内存占用大,数据一致性的问题,CopyOnWrite容器只能保证数据最终的一致性,不能保证数据实时一致性。鉴于它的这些缺点,可以使用ConcurrentHashMap容器。
实现原理:新增到容器的数据会放到一个新的容器中,然后将原容器的引用指向新容器,旧容器也会存在,因此会有两个容器占用内存。我们也可以用同样的方式实现自己的CopyOnWriteMap。
4、ConcurrentHashMap
ConcurrentHashMap同样是一个并发容器,将同步粒度最小化。
实现原理:ConcurrentHashMap默认是由16个Segment组成,每个Segment由多个Hashtable组成,数据变更需要经过两次哈希算法,第一次哈希定位到Segment,第二次哈希定位到Segment下的Hashtable,容器只会将单个Segment锁住,然后操作Segment下的Hashtable,多个Segment之间不受影响。如果需要扩容不是对Segment扩容而是对Segment下的Hashtable扩容。虽然经过两次哈希算法会使效率降低,但是比锁住整个容器效率要高得多。
5、BlockingQueue
BlockingQueue只是一个接口,它的实现类有ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、DelayQueue、LinkedBlockingDeque。
ArrayBlockingQueue:由数据支持的有界阻塞队列。
LinkedBlockingQueue:基于链接节点、范围任意的阻塞队列。
PriorityBlockingQueue:无界阻塞队列。
SynchronousQueue:一种阻塞队列,其中每个插入操作必须等待另一个线程的对应移除操作。
DelayQueue:Delayed元素的一个无界阻塞队列。
LinkedBlockingDeque:基于链接节点、范围任意的双端阻塞队列,可以在队列的两端添加、移除元素。
6、Lock
Lock分为公平锁和非公平锁,默认是非公平锁。实现类有ReetrantLock、ReetrantReadWriteLock,都依赖于AbstractQueuedSynchronizer抽象类。ReetrantLock将所有Lock接口的操作都委派到Sync类上,Sync有两个子类:NonFairSync和FaiSync,通过其命名就能知道分别处理非公平锁和公平锁的。AbstractQueuedSynchronizer把所有请求构成一个CLH队列,这里是一个虚拟队列,当有线程竞争锁时,该线程会首先尝试是否能获取锁,这种做法对于在队列中等待的线程来说是非公平的,如果有线程正在Running,那么通过循环的CAS操作将此线程增加到队尾,直至添加成功。
7、Atomic包
Atomic包下的类实现了原子操作,有对基本类型如int、long、boolean实现原子操作的类:AtomicInteger、AtomicLong、AtomicBoolean,如果需要对一个对象进行原子操作,也有对对象引用进行原子操作的AtomicReference类,还有对对象数组操作的原子类:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。原子操作核心思想是CAS操作,然后调用底层操作系统指令来实现。
㈥ java中ExecutorService的线程池如何暂停所有的任务和继续所有的任务 有这样的函数吗
Executor 提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。
可以关闭 ExecutorService,这将导致其拒绝新任务。提供两个方法来关闭 ExecutorService。shutdown() 方法在终止前允许执行以前提交的任务,而 shutdownNow() 方法阻止等待任务启动并试图停止当前正在执行的任务。在终止时,执行程序没有任务在执行,也没有任务在等待执行,并且无法提交新任务。应该关闭未使用的 ExecutorService 以允许回收其资源。
通过创建并返回一个可用于取消执行和/或等待完成的 Future,方法 submit 扩展了基本方法 Executor.execute(java.lang.Runnable)。方法 invokeAny 和 invokeAll 是批量执行的最常用形式,它们执行任务 collection,然后等待至少一个,或全部任务完成(可使用 ExecutorCompletionService 类来编写这些方法的自定义变体)。
Executors 类提供了用于此包中所提供的执行程序服务的工厂方法。
㈦ java 如何创建一个有返回值的线程
可以通过实现Callable接口创建一个有返回值的线程,代码如下:
importjava.util.concurrent.*;
<Integer>{
privateintcount;
publicMyThread(intcount){
this.count=count;
}
@Override
publicIntegercall()throwsException{
//此处是线程要处理的业务代码,此处实现的是对count变量加1的操作
count+=1;
Thread.sleep(1000);
returncount;
}
publicstaticvoidmain(String[]args){
//创建线程实例
MyThreadmyThread=newMyThread(1);
//创建一个大小为10的线程池
ExecutorServiceexecutor=Executors.newFixedThreadPool(10);
//将线程提交到线程池执行
Future<Integer>future=executor.submit(myThread);
try{
//调用get方法获取线程执行结果,在线程执行完成前该方法会一直阻塞
Integerresult=future.get();
System.out.println(result);
}catch(InterruptedExceptione){
e.printStackTrace();
}catch(ExecutionExceptione){
e.printStackTrace();
}
//try{
////这种写法可以设置线程执行的超时时间,当线程超过指定的时间还未执行完成时会抛出TimeoutException异常
////示例中表示线程超过1000毫秒还没执行完就会抛出超时异常
//Integerresult=future.get(1000,TimeUnit.MILLISECONDS);
//System.out.println(result);
//}catch(InterruptedExceptione){
//e.printStackTrace();
//}catch(ExecutionExceptione){
//e.printStackTrace();
//}catch(TimeoutExceptione){
//e.printStackTrace();
//}
}
}
㈧ 异步多线程----执行器(Executor)
如果 程序中创建了大量的生命期很短的线程 ,应该 使用线程池(thread pool) 。一个线程池中包含许多准备运行的空线程。将Runnable对象交给线程池,就会有一个线程调用run方法。当run方法退出时,线游枯程不会死亡,而是在池中准备为下一个请求提供服务。
另一个使用线程池的理由是减少并发线程的数目 。 创建大量线程会大大降低性能甚至使虚拟机崩溃 。如果有一个会创建许多线程的算法, 应该使用一个线程数“固定的”线程池 以限制并发线程的总数。
执行器(Executor)类有许多静态工厂方法用来构建线程池。
上面3个方法返回实现了ExecutorService接口 的 ThreadPoolExecutor类的对象 。
可以使用下面的方法 将一个Runnable对象或Callable对象提交给ExecutorService :
该线程池会在方便的时候尽早执行提交的任务。 调用submit时 , 会得到一个Future对象 ,可用来查询该任务的状态。
第一个submit方法返回一个Future<?>。可以使用这样一个对象来调用isDone、cancel或isCancelled。但是,get方法在完成的时候只是简单地返回null。
第二版本的Submit也提交一个Runnable,并且Future的get方法在完成的神哪洞时候返回指定的result对象。
第三个版本的Submit提交一个Callable,并且返回的Future对象将在计算结构准备好的时候得到它。
当用完一个线程池的时候,调用shutdown 。该方法 启动该池的关缓滚闭序列 。被关闭的执行器 不再接受新的任务 。当 所有任务都完成以后,线程池中的线程死亡 。另一种方法是调用 shutdownNow 。该池 取消尚未开始的所有任务并试图中断正在运行的线程 。
总结在使用线程池时应该做的事:
继续以一个计算匹配的文件数目程序为例:
ScheledExecutorService接口 具有 为预定执行 (Scheled Execution)或 重复执行任务而设计 的方法。它是一种允许使用线程池机制的java.util.Timer的泛化。Executors类的 newScheledThreadPool 和 方法 将返回实现了ScheledExecutorService接口的对象。
可以预定Runnable或Callable在初始的延迟之后只运行一次。也可以预定一个Runnable对象周期性地运行。详见API。
㈨ 如何在java中获取线程异步执行之后的结果
java中提供了Future<V>接口和实现了Future接口的FutureTask<V> 类来将线程执行之后的结果返回(通过get()方法)。
1.Future<V>接口
Runnable接口执行任务是不返回任何值的,Runnable的run()方法的执行结果是void,而Future接口的call方法是有返回结果的,这是Runnable跟Future的区别之一,它们的另一个不同之处就是实现了Runnable接口的任务执行是调用ExecutorService的execute(Runnable task)方法,而实现了Future接口的任务是调用ExecutorService的submit(Future task)方法。调用Future的get()方法就能直接得到任务的返回值,该方法会一直阻塞直到任务的结果出来为止,我们可以调用Future的isDone()方法来判断该任务的结果是否准备就绪。
[java] view plain
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class TestFuture {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newCachedThreadPool();
Future result1 = executor.submit(new Callable() {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
return sum;
}
});
Future result2 = executor.submit(new Callable() {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 10; i < 100; i++) {
sum += i;
}
return sum;
}
});
executor.shutdown();
System.out.println(result1.get() + result2.get());
}
}
2.FutureTask类
FutureTask实现了Future接口,将一个Callable实例作为参数传给它,就能创建一个FutureTask实例,然后用ExecutorService的submit方法来执行这个实例。最后同样是用get方法获取线程执行后的结果。
[plain] view plain
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class TestFutureTask {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newCachedThreadPool();
Callable task = new Callable() {
@Override
public String call() throws Exception {
return "结果";
}
};
FutureTask ft = new FutureTask(task);
executor.submit(ft);
System.out.println(ft.get());
executor.shutdown();
}
}empty
㈩ 在java中executor和executors的区别
它是"执行者"接口,它是来执行任务的。准确的说,Executor提供了execute()接口蠢孙来执行已提交的 Runnable 任务的对象。Executor存带态链在的目的是提供一种将"任务提交闭扰"与"任务如何运行"分离开来的机制。它只包含一个函数接口。
2. Executors
Executors是个静态工厂类。它通过静态工厂方法返回ExecutorService、ScheledExecutorService、ThreadFactory 和 Callable 等类的对象。
3. ExecutorService
ExecutorService继承于Executor。它是"执行者服务"接口,它是为"执行者接口Executor"服务而存在的;准确的话,ExecutorService提供了"将任务提交给执行者的接口(submit方法)","让执行者执行任务(invokeAll, invokeAny方法)"的接口等等。