线程的创建和管理:

1.应用Thread类显式创建、管理线程

2.应用Executor创建并管理线程。

定义任务:

无返回的任务:实现Runnable接口并编写run()方法。

有响应的任务:实现Callable接口并编写call()方法。

如下的火箭发射倒计时任务:

public class Lunch implements Runnable {

  int countDown = 9;
  int taskCount = 0;
  int rocketNum = 9;
  final int id = taskCount++;
  final static Logger log = Logger.getLogger("lavasoft");
  Logger log1 = Logger.getLogger("lavasoft");
  Logger log2 = Logger.getLogger("lavasoft.blog");

  public Lunch(){
  }

  public Lunch(int countDown,int rocketNum){
    this.countDown=countDown;
    this.rocketNum=rocketNum;
  }

  public void status(int rocketNum){
    while(countDown>=0){
      if(countDown==0){
        log.info("火箭"+rocketNum+"发射成功!");
        countDown--;
      }else{
        log.info("火箭"+rocketNum+"将在"+countDown+"秒后发射!");
        countDown--;
    }
  }
}
@Override
  public void run() {
  // TODO Auto-generated method stub
    status(rocketNum);
  }

  public static void main(String args[]) throws SecurityException, IOException{

    FileHandler fileHandler = new FileHandler("C:/testlog.log");
    fileHandler.setLevel(Level.INFO);
    fileHandler.setFormatter(new MyLogHander());
    ExecutorService exec = Executors.newCachedThreadPool();// 需要多少线程创建多少线程,用多少给多少。
    ExecutorService exec2 = Executors.newSingleThreadExecutor();// 保证任意时刻任何线程中都只有唯一的任务在运行。
    ExecutorService exec3 = Executors.newFixedThreadPool(2);//指定线程数量。
    ExecutorService exec4 = Executors.newScheduledThreadPool(2);//可实现周期性或延迟任务
    log.addHandler(fileHandler);
    for(int rocketNum=1;rocketNum<10;rocketNum++){
//用Thread类显式创建并管理线程

Thread t1 = new Thread(new Lunch(6,rocketNum));

t1.start();

//用Executor类创建并管理线程
exec.execute(new Lunch(6,rocketNum));
exec2.execute(new Lunch(6,rocketNum));
exec3.execute(new Lunch(6,rocketNum));
      exec4.execute(new Lunch(6,rocketNum));
      log.info("等待火箭"+rocketNum+"发射");
    }
    exec.shutdown();
  }

}

class MyLogHander extends Formatter{
@Override
  public String format(LogRecord record) {
  return record.getLevel() + ":" + record.getMessage()+"\n";
  }
}

public class Lunch implements Callable<String> {

  int countDown = 9;
  int taskCount = 0;
  int rocketNum = 9;
  final int id = taskCount++;
  final static Logger log = Logger.getLogger("lavasoft"); 
  Logger log1 = Logger.getLogger("lavasoft"); 
  Logger log2 = Logger.getLogger("lavasoft.blog");

  public Lunch(){
  }

  public Lunch(int countDown,int rocketNum){
    this.countDown=countDown;
    this.rocketNum=rocketNum;
  }

  public void status(int rocketNum){
    while(countDown>=0){
      if(countDown==0){
        log.info("火箭"+rocketNum+"发射成功!");
        countDown--;
      }else{
        log.info("火箭"+rocketNum+"将在"+countDown+"秒后发射!");
        countDown--;
    }
  }
}
  @Override
  public String call() {
  // TODO Auto-generated method stub
    status(rocketNum);

    return "***火箭"+rocketNum+"发射完毕***";
  }

  public static void main(String args[]) throws SecurityException, IOException{

    FileHandler fileHandler = new FileHandler("C:/testlog.log"); 
    fileHandler.setLevel(Level.INFO);
    fileHandler.setFormatter(new MyLogHander()); 
    ExecutorService exec = Executors.newCachedThreadPool();// 需要多少线程创建多少线程,用多少给多少。
    ExecutorService exec2 = Executors.newSingleThreadExecutor();// 保证任意时刻任何线程中都只有唯一的任务在运行。
    ExecutorService exec3 = Executors.newFixedThreadPool(2);//指定线程数量。
    ExecutorService exec4 = Executors.newScheduledThreadPool(2);//可实现周期性或延迟任务
    log.addHandler(fileHandler);

    List<Future<String>> list = new ArrayList<Future<String>>();

    for(int rocketNum=1;rocketNum<10;rocketNum++){
//用Thread类显式创建并管理线程

Thread t1 = new Thread(new Lunch(6,rocketNum));

t1.start();

//用Executor类创建并管理线程
exec.execute(new Lunch(6,rocketNum));
exec2.execute(new Lunch(6,rocketNum));
exec3.execute(new Lunch(6,rocketNum));
    Future<String> a = exec.submit(new Lunch(6,rocketNum));//call方法会返回一个Future对象,与runnable不同,将任务赋予给线程时,必须用submit方法。
    list.add(a);
    try {
      System.out.println(a.get());
    } catch (InterruptedException | ExecutionException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
      log.info("等待火箭"+rocketNum+"发射");
    }
    exec.shutdown();
  }

}

class MyLogHander extends Formatter{
@Override 
  public String format(LogRecord record) { 
  return record.getLevel() + ":" + record.getMessage()+"\n"; 
  } 
}

总结:

Callable接口和Runnable接口相似,区别就是Callable需要实现call方法,而Runnable需要实现run方法;并且,call方法还可以返回任何对象,无论是什么对象,JVM都会当作Object来处理。但是如果使用了泛型,我们就不用每次都对Object进行转换了。

Runnable和Callable都是接口

不同之处:
1.Callable可以返回一个类型V,而Runnable不可以
2.Callable能够抛出checked exception,而Runnable不可以
3.Runnable是自从java1.1就有了,而Callable是1.5之后才加上去的
4.Callable和Runnable都可以应用于executors。而Thread类只支持Runnable.
上面只是简单的不同,其实这两个接口在用起来差别还是很大的。Callable与executors联合在一起,在任务完成时可立刻获得一个更新了的Future。而Runable却要自己处理

Future接口,一般都是取回Callable执行的状态用的。其中的主要方法:

  • cancel,取消Callable的执行,当Callable还没有完成时
  • get,获得Callable的返回值
  • isCanceled,判断是否取消了
  • isDone,判断是否完成

用Executor来构建线程池,应该要做的事:

1).调用Executors类中的静态方法newCachedThreadPool(必要时创建新线程,空闲线程会被保留60秒)或newFixedThreadPool(包含固定数量的线程池)等,返回的是一个实现了ExecutorService接口的ThreadPoolExecutor类或者是一个实现了ScheduledExecutorServiece接口的类对象。

2).调用submit提交Runnable或Callable对象。

3).如果想要取消一个任务,或如果提交Callable对象,那就要保存好返回的Future对象。

4).当不再提交任何任务时,调用shutdown方法

Java并发基础:线程的创建的更多相关文章

  1. Java并发基础--线程通信

    java中实现线程通信的四种方式 1.synchronized同步 多个线程之间可以借助synchronized关键字来进行间接通信,本质上是通过共享对象进行通信.如下: public class S ...

  2. Java 并发基础——线程安全性

    当线程安全:多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协调,这个类都能表现出正确的行为,那么久称这个类是线程安全的. 在线程 ...

  3. Java并发基础--线程安全

    一.线程安全 1.线程安全的概念 线程安全:某个类被单个线程,或者多个线程同时访问,所表现出来的行为是一致,则可以说这个类是线程安全的. 2.什么情况下会出现线程安全问题 在单线程中不会出现线程安全问 ...

  4. java并发编程 线程基础

    java并发编程 线程基础 1. java中的多线程 java是天生多线程的,可以通过启动一个main方法,查看main方法启动的同时有多少线程同时启动 public class OnlyMain { ...

  5. Java并发编程:如何创建线程?

    Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...

  6. Java并发编程:线程和进程的创建(转)

    Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...

  7. 【转】Java并发编程:如何创建线程?

    一.Java中关于应用程序和进程相关的概念 在Java中,一个应用程序对应着一个JVM实例(也有地方称为JVM进程),一般来说名字默认是java.exe或者javaw.exe(windows下可以通过 ...

  8. java并发基础(五)--- 线程池的使用

    第8章介绍的是线程池的使用,直接进入正题. 一.线程饥饿死锁和饱和策略 1.线程饥饿死锁 在线程池中,如果任务依赖其他任务,那么可能产生死锁.举个极端的例子,在单线程的Executor中,如果一个任务 ...

  9. 2、Java并发编程:如何创建线程

    Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...

  10. Java 并发基础

    Java 并发基础 标签 : Java基础 线程简述 线程是进程的执行部分,用来完成一定的任务; 线程拥有自己的堆栈,程序计数器和自己的局部变量,但不拥有系统资源, 他与其他线程共享父进程的共享资源及 ...

随机推荐

  1. C++二叉树结构的建立和操作

    二叉树是数据结构中的树的一种特殊情况,有关二叉树的相关概念,这里不再赘述,如果不了解二叉树相关概念,建议先学习数据结构中的二叉树的知识点. 准备数据 定义二叉树结构操作中需要用到的变量及数据等. #d ...

  2. Luogu 2900 [USACO08MAR]土地征用Land Acquisition

    斜率优化dp. 首先发现如果存在$x$和$y$使得$len(x) \geq len(y)$并且$wid(x) \geq wid(y)$,那么$y$直接不考虑就好了,因为在买$x$的时候就把$y$顺便带 ...

  3. SPOJ-TTM To the moon

    一句话题意:写一个支持区间修改,区间求和的可持久化数据结构. 考虑使用主席树,然而,区间修改怎么办? 似乎有标记永久化的方法. 对于线段树上完全覆盖标记产生贡献的区间,我们直接打上一个$tag$,而对 ...

  4. Java堆内存划分

    根据对象的存活率(年龄)Java堆内存划分为3种,新生代,老年代,永久代: 1.新生代 比如我们在方法中区new一个对象,那这方法调用完毕后,对象就会被回收,这就是一个典型的新生代对象. 现在的商业虚 ...

  5. 关于奇异值分解(SVD)的理解

    奇异值分解实际上是将一个矩阵,分解成为两个不同维度(行数和列数)上的正交向量集之间的映射变换,奇异值则是变换时的缩放! 例如上面的矩阵M就是一个5维映射到4维的变换矩阵,而SVD分解得到的奇异值和奇异 ...

  6. Java实现WC基本功能

    GitHub仓库:https://github.com/douyazai/WCbase 一.WC 项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写一个命 ...

  7. 【转-mysql-explain介绍】

    explain显示了MySQL如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 先解析一条sql语句,看出现什么内容 EXPLAINSELECTs.uid, ...

  8. ASP.NET十分有用的页面间传值方法(转)

    一.目前在ASP.NET中页面传值共有这么几种方式: 1.表单提交,   <form action= "target.aspx" method = "post&qu ...

  9. jquery筛选元素函数

    jquery筛选元素函数 1.过滤匹配第二个p元素: $("button").click(function(){ $("p").eq(1).css(" ...

  10. python字符串和日期相互转换