㈠ 如何创建线程如何保证线程安全
创建线程的方式一:继承Thread类(由于java单继承的特性,这种方式用的比较少)
步骤:
1、继承Thread类,然后重写run方法
2、创建实现类对象、代理类对象,然后代理类对象调用start()方法启动线程
用实现Runnable接口的方式,实现多线程:
《模拟抢票系统》,代码如下:
线程调用了start()方法,并不意味着立即执行,而是到就绪状态,等待cpu的调度,所以每次执行的结果都是不一样的。
创建线程的方式三:实现java.util.concurrent并发包下的Callable接口(进阶版,初学者做个了解)
步骤:
1、创建一个类实现Callable接口,然后重写call()方法
(和run方法不一样的是,call方法可以有返回值,并且可以抛出异常)
2、创建Callable的实现类对象--》创建执行服务--》提交执行服务得到Future对象--》获取结果--》停止服务
㈡ java Future 阻塞
有区别。比如你要查3次,每次分别耗时1s,2s,3s,用单线程,这个线程就会阻塞3次,总共耗时等于这3次查询的总耗时,是6s;而如果用了3个线程来查,每个线程都用Future 的get方法来返回数据,这样就是3个阻塞发生在同一时间,前两个完成了会继续等待第三个查询完成,最终耗时是时间最长的那个查询,是3s。
㈢ java future函数的作用
在并发编程时,一般使用runnable,然后扔给线程池完事,这种情况下不需要线程的结果。
所以run的返回值是void类型。
如果是一个多线程协作程序,比如菲波拉切数列,1,1,2,3,5,8...使用多线程来计算。
但后者需要前者的结果,就需要用callable接口了。
callable用法和runnable一样,只不过调用的是call方法,该方法有一个泛型返回值类型,你可以任意指定。
线程是属于异步计算模型,所以你不可能直接从别的线程中得到函数返回值。
这时候,Future就出场了。Futrue可以监视目标线程调用call的情况,当你调用Future的get()方法以获得结果时,当前线程就开始阻塞,直接call方法结束返回结果。
㈣ java中怎样得到线程结束的通知
runnable 现成结束不通知,但是 run方法运行到最后一行就算结束了。
Callable 也可是实现通知。
MyCallable task2 = new MyCallable(1);
MyCallable task3 = new MyCallable(2);
MyCallable task1 = new MyCallable(0);
// 创建一个执行任务的服务
ExecutorService es = Executors.newFixedThreadPool(3);
// 提交并执行任务,任务启动时返回了一个Future对象,
// 如果想得到任务执行的结果或者是异常可对这个Future对象进行操作
Future future1 = es.submit(task1);
// 获得第一个任务的结果,如果调用get方法,当前线程会等待任务执行完毕后才往下执行
System.out.println("task1: " + future1.get());
Future future2 = es.submit(task2);
// 等待5秒后,再停止第二个任务。因为第二个任务进行的是无限循环
Thread.sleep(5000);
System.out.println("task2 cancel: " + future2.cancel(true));
// 获取第三个任务的输出,因为执行第三个任务会引起异常
// 所以下面的语句将引起异常的抛出
Future future3 = es.submit(task3);
System.out.println("task3: " + future3.get());
㈤ java协程和futuretask的区别
Callable要采用ExecutorSevice的submit方法提交,返回Future对象,通过Future的get()方法,同步拿到线程的返回结果,实例代码如下:
public class ThreadExample12 { public static void main(String[] args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<String> future = threadPool.submit(new Callable<String>() { public String call() throws Exception {
Thread.sleep(2000); return "Hello World";
};
});
System.out.println("等待结果"); try {
System.out.println("返回结果为:" + future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Future取得的结果类型和Callable返回的结果类型必须一致,这是通过泛型来实现的。Callable要采用ExecutorSevice的submit方法提交,返回的Future对象可以取消任务,通过调用Future的future.cancel(true)方法实现,Future对象还可以对超时线程进行关闭,通过future.wait(3);如果线程耗时超过3秒则抛出异常
在这里有人可能会有疑问,既然要同步返回结果,那我为什么要再开一个线程去执行呢,还不如直接在主线程执行就好。但是这种是局限于在一个线程时,如果需要同时执行多个线程,等待多个线程返回结果时,在主线程中是不能实现这种功能的。可以看一下实例代码,就能明白了:
public class ThreadExample13 { public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(10);
CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool); for (int i = 1; i <= 10; i++) {
final int seq = i;
completionService.submit(new Callable<Integer>() {
@Override public Integer call() throws Exception {
Thread.sleep(new Random().nextInt(5000)); return seq;
}
});
} for (int i = 0; i < 10; i++) { try {
System.out.println(completionService.take().get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}