Java多线程并发技术

参考文献:

http://blog.csdn.net/aboy123/article/details/38307539

http://blog.csdn.net/ghsau/article/category/1707779

http://www.iteye.com/topic/366591

JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。

1、 继承Thread类实现多线程

public class MyThread extends Thread {

  public void run() { //重写run方法

   System.out.println("MyThread.run()");

  }

}

//调用代码

MyThread myThread1 = new MyThread();

MyThread myThread2 = new MyThread();

myThread1.start(); // 启动线程

myThread2.start();

Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()实例方法

2、 实现Runnable接口方式实现多线程

//如果自己的类已经extends另一个类,就无法直接extends Thread,此时,必须实现一个Runnable接口,如下:

public class MyThread extends OtherClass implements Runnable {

  public void run() {

   System.out.println("MyThread.run()");

  }

}

//为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例:

MyThread myThread = new MyThread();

Thread thread = new Thread(myThread);

thread.start();

3、 使用ExecutorService、Callable、Future实现有返回结果的多线程

ExecutorService、Callable、Future这个对象实际上都是属于Executor框架中的功能类。可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口。执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了,再结合线程池接口ExecutorService就可以实现有返回结果的多线程了。

  1. int taskSize = 5;
  2. ExecutorService pool = Executors.newFixedThreadPool(taskSize);  // 创建一个线程池
  3. // 创建多个有返回值的任务
  4. List<Future> list = new ArrayList<Future>();
  5. for (int i = 0; i < taskSize; i++) {
  6. Callable c = new MyCallable(i + " ");
  7. Future f = pool.submit(c);      // 执行任务并获取Future对象
  8. list.add(f);
  9. }
  10. pool.shutdown();    // 关闭线程池
  11. for (Future f : list) {
  12. // 从Future对象上获取任务的返回值,并输出到控制台
  13. System.out.println(">>>" + f.get().toString());   //get()是阻塞调用
  14. }

// 实现Callable接口

  1. class MyCallable implements Callable<Object> {
  2. private String taskNum;
  3. MyCallable(String taskNum) {
  4. this.taskNum = taskNum;
  5. }
  6. public Object call() throws Exception {
  7. Thread.sleep(1000);
  8. return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】";
  9. }
  1. }

4、 Executors类说明:

参考文献:http://www.iteye.com/topic/366591

Executors类,提供了一系列工厂方法用于创建线程池,返回的线程池都实现了ExecutorService接口。

public static ExecutorService newFixedThreadPool(int nThreads)

创建固定数目线程的线程池。

public static ExecutorService newCachedThreadPool()

创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。

public static ExecutorService newSingleThreadExecutor()

创建一个单线程化的Executor。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。

ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。

5、 其他获得线程执行结果的方式:

http://blog.csdn.net/ghsau/article/details/7451464

基于FutureTask

在上述实现中,任务callable被提交后返回一个future用于获得执行结果;

FutureTask实现了两个接口,Runnable和Future,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值;

  1. public class CallableAndFuture {
  2. public static void main(String[] args) {
  3. Callable<Integer> callable = new Callable<Integer>() {
  4. public Integer call() throws Exception {
  5. return new Random().nextInt(100);
  6. }
  7. };
  8.          FutureTask<Integer> future = new FutureTask<Integer>(callable);  
  9.  new Thread(future).start();  
  10. try {
  11. Thread.sleep(5000);// 可能做一些事情
  12. System.out.println(future.get());
  13. catch (InterruptedException e) {
  14. e.printStackTrace();
  15. catch (ExecutionException e) {
  16. e.printStackTrace();
  17. }
  18. }

19.  }

基于CompletionService的实现方式

  1. public class CallableAndFuture {
  2. public static void main(String[] args) {
  3.      ExecutorService threadPool = Executors.newCachedThreadPool();  
  4.         CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(threadPool);
  5. for(int i = 1; i < 5; i++) {
  6. final int taskID = i;
  7. cs.submit(new Callable<Integer>() {
  8. public Integer call() throws Exception {
  9. return taskID;
  10. }
  11. });
  12. }
  13. // 可能做一些事情
  14. for(int i = 1; i < 5; i++) {
  15. try {

//take 每次获得一个执行完成的future,如果没有就阻塞,与其功能相同的非阻塞调用时poll

  1. System.out.println(cs.take().get());
  2. catch (InterruptedException e) {
  3. e.printStackTrace();
  4. catch (ExecutionException e) {
  5. e.printStackTrace();
  6. }
  7. }
  8. }

}

6、 多线程相关函数:

参考文献:http://blog.csdn.net/ghsau/article/details/17560467

线程中断:http://blog.csdn.net/z69183787/article/details/25076033

void

interrupt()  //    中断线程。其实只是设置了中断标志位

static boolean

interrupted() //  测试调用该方法的当前线程是否已经中断。同时清除中断标志位

boolean

isInterrupted() // 测试this线程是否已经中断。不清除中断标志位

线程让步

static void

yield() //     暂停当前正在执行的线程对象,并执行其他线程

注意: 如果存在synchronized线程同步的话,线程让步不会释放锁(监视器对象)

线程休眠:

static void

sleep(long millis)//  在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。

注意: 如果存在synchronized线程同步的话,线程休眠不会释放锁(监视器对象),但会释放cpu

线程合并:http://uule.iteye.com/blog/1101994

 void

join()          等待该线程终止。

 void

join(long millis)          等待该线程终止的时间最长为 millis 毫秒。

 void

join(long millis, int nanos) 等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。

线程合并是优先执行调用该方法的线程,再执行当前线程。内部是用wait方法实现的

  1. public class JoinTest {
  2. public static void main(String[] args) throws InterruptedException {
  3. JoinThread t1 = new JoinThread("t1");
  4. JoinThread t2 = new JoinThread("t2");
  5. t1.start();   //启动线程
  6. t2.start();  //启动线程
  7. t1.join();   //等待该线程执行完毕
  8. t2.join();  //
  9. System.out.println("主线程开始执行!");
  10. }

11. }

class JoinThread extends Thread {

  1. public JoinThread(String name) {
  2. super(name);
  3. }
  4. public void run() {
  5. for(int i = 1; i <= 10; i++)
  6. System.out.println(getName() + getId() + "执行了" + i + "次");
  7. }

}

7、 线程同步之锁

连接:http://blog.csdn.net/ghsau/article/details/7461369

Java多线程并发技术的更多相关文章

  1. Java 多线程并发编程一览笔录

    Java 多线程并发编程一览笔录 知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run ...

  2. Java多线程并发04——合理使用线程池

    在此之前,我们已经了解了关于线程的基本知识,今天将为各位带来,线程池这一技术.关注我的公众号「Java面典」了解更多 Java 相关知识点. 为什么使用线程池?线程池做的工作主要是控制运行的线程的数量 ...

  3. Java多线程-并发容器

    Java多线程-并发容器 在Java1.5之后,通过几个并发容器类来改进同步容器类,同步容器类是通过将容器的状态串行访问,从而实现它们的线程安全的,这样做会消弱了并发性,当多个线程并发的竞争容器锁的时 ...

  4. java 多线程并发问题总结

    java 多线程并发主要通过关键字synchronized实现 Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问 ...

  5. 从火箭发场景来学习Java多线程并发闭锁对象

    从火箭发场景来学习Java多线程并发闭锁对象 倒计时器场景 在我们开发过程中,有时候会使用到倒计时计数器.最简单的是:int size = 5; 执行后,size—这种方式来实现.但是在多线程并发的情 ...

  6. Java多线程并发03——在Java中线程是如何调度的

    在前两篇文章中,我们已经了解了关于线程的创建与常用方法等相关知识.接下来就来了解下,当你运行线程时,线程是如何调度的.关注我的公众号「Java面典」了解更多 Java 相关知识点. 多任务系统往往需要 ...

  7. Java多线程并发02——线程的生命周期与常用方法,你都掌握了吗

    在上一章,为大家介绍了线程的一些基础知识,线程的创建与终止.本期将为各位带来线程的生命周期与常用方法.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程生命周期 一个线程不是被创建了 ...

  8. Java多线程并发05——那么多的锁你都了解了吗

    在多线程或高并发情境中,经常会为了保证数据一致性,而引入锁机制,本文将为各位带来有关锁的基本概念讲解.关注我的公众号「Java面典」了解更多 Java 相关知识点. 根据锁的各种特性,可将锁分为以下几 ...

  9. Java多线程并发07——锁在Java中的实现

    上一篇文章中,我们已经介绍过了各种锁,让各位对锁有了一定的了解.接下来将为各位介绍锁在Java中的实现.关注我的公众号「Java面典」了解更多 Java 相关知识点. 在 Java 中主要通过使用sy ...

随机推荐

  1. sass相关随笔

    安装 下载ruby并且安装 点击这里 打开命令行输入 gem install sass 我使用的是sublime text3 还需要下载三个插件 sass -- 可以帮助你语法高亮 sass buil ...

  2. ArcGIS中合并空间有压盖关系的要素属性

    1.前言 在客户单位, 被客户问道这样一个问题“如何合并两个有压盖关系图层的属性信息?” 在工具箱里面可以使用以下工具解决: 2.处理过程 (1)在工具箱中选择Spatial Join工具,并设置相关 ...

  3. python3对多线程处理

    参考博客: https://blog.csdn.net/u010339879/article/details/86506450 https://blog.csdn.net/qq_33961117/ar ...

  4. Spring 的AOP

    AOP:面向切面编程,相对于OOP面向对象的编程 Spring的AOP的存在的目的是为了解耦.AOP可以让一组类共享相同的行为.在OOP中只能通过继承类和实现接口,来使代码的耦合度增强,且类继承只能为 ...

  5. CST,CET,UTC,GMT,DST,Unix时间戳几种常见时间概述与关系(转)

    转自:http://www.cnblogs.com/frontendBY/p/5215785.html 1.UTC: Universal Time Coordinated 协调世界时,又称世界标准时间 ...

  6. arcgis api for js 地图查询

      arcgis api for js入门开发系列四地图查询(含源代码) 上一篇实现了demo的地图工具栏,本篇新增地图查询功能,包括属性查询和空间查询两大块,截图如下: 属性查询效果图: 空间查询效 ...

  7. 判断一个点是否在多边形区域内--C算法

    /*函数的输入:(1)当前点的坐标p(2)区域顶点数组pt[]:(3)顶点数nCount 输出: 在区域内返回TRUE,否则返回FALSE.  Point类型是一个结构: struct Point { ...

  8. IOS 绘制基本图形( 画圆、画线、画圆弧、绘制三角形、绘制四边形)

    // 当自定义view第一次显示出来的时候就会调用drawRect方法- (void)drawRect:(CGRect)rect { // 1.获取上下文 CGContextRef ctx = UIG ...

  9. bzoj3312: [Usaco2013 Nov]No Change

    题意: K个硬币,要买N个物品.K<=16,N<=1e5 给定买的顺序,即按顺序必须是一路买过去,当选定买的东西物品序列后,付出钱后,货主是不会找零钱的.现希望买完所需要的东西后,留下的钱 ...

  10. 2018.10.05 TOPOI提高组模拟赛 解题报告

    得分: \(100+5+100=205\)(真的是出乎意料) \(T1\):抵制克苏恩(点此看题面) 原题: [BZOJ4832][Lydsy1704月赛] 抵制克苏恩 应该还是一个比较简单的\(DP ...