java线程——三种创建线程的方式
前言
线程,英文Thread。在java中,创建线程的方式有三种:
1、Thread
2、Runnable
3、Callable
在详细介绍下这几种方式之前,我们先来看下Thread类和Runnable接口。
Runnable接口
接口中只有一个run()方法,等待实现类去实现。
- 
package java.lang;
- 
@FunctionalInterface
- 
public interface Runnable {
- 
 
- 
    public abstract void run();
- 
}
Thread类
该类实现了Runnable接口,也提供了很多其他的方法,如yield(),join()等
- 
package java.lang;
- 
public
- 
class Thread implements Runnable {
- 
	//获取当前线程
- 
	public static native Thread currentThread();
- 
	public static native void yield();
- 
	//一系列的构造函数
- 
	 public Thread(Runnable target, String name) {
- 
        init(null, target, name, 0);
- 
    }
- 
	 public Thread(ThreadGroup group, String name) {
- 
        init(group, null, name, 0);
- 
    }
- 
	/*调用该方法时,jvm会调用run方法
- 
	*Causes this thread to begin execution; the Java Virtual Machine
- 
    * calls the run method of this thread.
- 
	*/
- 
	public synchronized void start() {
- 
       
- 
        if (threadStatus != 0)
- 
            throw new IllegalThreadStateException();
- 
 
- 
        group.add(this);
- 
 
- 
        boolean started = false;
- 
        try {
- 
            start0();
- 
            started = true;
- 
        } finally {
- 
            try {
- 
                if (!started) {
- 
                    group.threadStartFailed(this);
- 
                }
- 
            } catch (Throwable ignore) {
- 
               
- 
            }
- 
        }
- 
    }
- 
 
- 
}
一、实现Runnable接口
- 
public class i_Runnable {
- 
 
- 
	/**
- 
	 * 主线程main方法
- 
	 * @param args
- 
	 */
- 
	public static void main(String[] args) {
- 
		for (int i = 0; i < 100; i++) {
- 
			System.out.println(Thread.currentThread().getName() + "====" + i);
- 
			if (i == 20) {
- 
				RunnableThreadTest rtt = new RunnableThreadTest();
- 
				//子线程
- 
				new Thread(rtt, "new Thread[1]====").start();
- 
				//new Thread(rtt, "新线程2").start();
- 
			}
- 
		}
- 
 
- 
	}
- 
/**
- 
 * RunnableThreadTest实现Runnable接口
- 
 * @author YANG
- 
 *
- 
 */
- 
	static class RunnableThreadTest implements Runnable {
- 
		private int i;
- 
 
- 
		@Override
- 
		public void run() {
- 
			for (i = 0; i < 100; i++) {
- 
				System.out.println(Thread.currentThread().getName() + " " + i);
- 
			}
- 
 
- 
		}
- 
 
- 
	}
- 
}
执行结果:
注意:
** 执行结果只截取了部分内容。
** 如果RunnableThreadTest类前不加static,会报错No enclosing instance of type i_Runnable is accessible. Must qualify the allocation with
 an enclosin。因为只有内部类修饰为静态时,才可以在静态类方法(main方法)中调用该类的成员变量和方法。
二、继承Thread类
- 
public class a_Thread {
- 
	public static void main(String[] args) {
- 
		Runner1 r=new Runner1();
- 
		r.start(); //已经有thread 不需要new,直接调用start即可。
- 
		
- 
		
- 
		for (int i = 0; i < 100; i++) {
- 
			System.out.println("main Thread:"+i);
- 
		}
- 
	}
- 
	
- 
	//Runner1继承Thread类,重写run方法
- 
	static class Runner1 extends Thread{
- 
		@Override
- 
		public void run() {
- 
		
- 
			for (int i = 0; i < 100; i++) {
- 
				System.out.println("Runner1:"+i);
- 
			}
- 
			
- 
		}
- 
		
- 
	}
- 
}
思考:能不能将上面的r.start(); 改为 r.run();
分析:换成run()方法之后,就变成了普通的方法调用,只有一个主线程,没有子线程。
执行结果:为了方便显示,我们将循环次数改为10。
- 
Runner1:0
- 
Runner1:1
- 
Runner1:2
- 
Runner1:3
- 
Runner1:4
- 
Runner1:5
- 
Runner1:6
- 
Runner1:7
- 
Runner1:8
- 
Runner1:9
- 
main Thread:0
- 
main Thread:1
- 
main Thread:2
- 
main Thread:3
- 
main Thread:4
- 
main Thread:5
- 
main Thread:6
- 
main Thread:7
- 
main Thread:8
- 
main Thread:9
三、实现Callable接口
前面两种方式是传统的线程技术中的内容,第三种方式Callable和Future是jdk1.5之后新增的。我们先来补充点东西,看看这种方式与之前的方式有什么联系。
- 
//实现Callable接口
- 
public class j_CallableTest implements Callable<String> {
- 
	public static void main(String[] args) {
- 
		j_CallableTest test=new j_CallableTest();
- 
		FutureTask<String> ft=new FutureTask<>(test);
- 
		
- 
		for (int i = 0; i < 100; i++) {
- 
			System.out.println(Thread.currentThread().getName()+" i的值为="+i);
- 
			if(i==20){
- 
				new Thread(ft,"子线程").start();
- 
			}
- 
		}
- 
	}
- 
 
- 
	//重写call方法
- 
	@Override
- 
	public String call() throws Exception {
- 
		int i = 0;
- 
		String reString = "";
- 
		for (; i < 100; i++) {
- 
			reString = Thread.currentThread().getName() + " " + i;
- 
			System.out.println(reString);
- 
		}
- 
		return reString;
- 
	}
- 
}
从上面可以看到,new Thread的方式还是用的public Thread(Runnable target, String name); 说明FutureTask也是Runnable类型的,他们之间的关系可以从下图中看出来。
那么,使用Callable和Future的方式有什么特点呢?
我们从他们的定义来看,Callable接口中只有一个方法,返回值为V。前两种方式都是返回void。
- 
@FunctionalInterface
- 
public interface Callable<V> {
- 
    /**
- 
     * Computes a result, or throws an exception if unable to do so.
- 
     *
- 
     * @return computed result
- 
     * @throws Exception if unable to compute a result
- 
     */
- 
    V call() throws Exception;
- 
}
小结:
1、接口实现更灵活,java不支持多继承。在这方面,Runnable和Callable更有优势。
2、返回值问题。Runnable和Thread都不能有返回值,但Callable可以,而且支持多种类型的数据。
就这两点来看,新增的Callable和Future的实现方式优势十分明显啊。但是追到原理,其实这三种都可以归结为一种方式。
java线程——三种创建线程的方式的更多相关文章
- 【Java 线程的深入研究1】Java 提供了三种创建线程的方法
		Java 提供了三种创建线程的方法: 通过实现 Runnable 接口: 通过继承 Thread 类本身: 通过 Callable 和 Future 创建线程. 1.通过实现 Runnable 接口来 ... 
- JavaScript DOM三种创建元素的方式
		三种创建元素的方式: document.write() element.innerHTML document.createElement() 初始HTML内容: <button>btn&l ... 
- java线程(1)——三种创建线程的方式
		前言 线程,英文Thread.在java中,创建线程的方式有三种: 1.Thread 2.Runnable 3.Callable 在详细介绍下这几种方式之前,我们先来看下Thread类和Runnabl ... 
- Java多线程学习总结--线程概述及创建线程的方式(1)
		在Java开发中,多线程是很常用的,用得好的话,可以提高程序的性能. 首先先来看一下线程和进程的区别: 1,一个应用程序就是一个进程,一个进程中有一个或多个线程.一个进程至少要有一个主线程.线程可以看 ... 
- 线程系列1--Java创建线程的几种方式及源码分析
		线程--创建线程的几种方式及源码分析 开始整理下线程的知识,感觉这块一直是盲区,工作中这些东西一直没有实际使用过,感觉也只是停留在初步的认识.前段时间一个内推的面试被问到,感觉一脸懵逼.面试官说,我的 ... 
- Servlet三种创建方式
		直接实现 Servlet 接口不太方便,所以 Servlet 又内置了两个 Servlet 接口的实现类(抽象类),分别为 GenericServlet 和 HttpServlet,因此,创建 Ser ... 
- Django多对多表的三种创建方式,MTV与MVC概念
		MTV与MVC MTV模型(django): M:模型层(models.py) T:templates V:views MVC模型: M:模型层(models.py) V:视图层(views.py) ... 
- Django-多对多关系的三种创建方式-forms组件使用-cookie与session-08
		目录 表模型类多对多关系的三种创建方式 django forms 组件 登录功能手写推理过程 整段代码可以放过来 forms 组件使用 forms 后端定义规则并校验结果 forms 前端渲染标签组件 ... 
- Js基础知识4-函数的三种创建、四种调用(及关于new function()的解释)
		在js中,函数本身属于对象的一种,因此可以定义.赋值,作为对象的属性或者成为其他函数的参数.函数名只是函数这个对象类的引用. 函数定义 // 函数的三种创建方法(定义方式) function one( ... 
随机推荐
- 使用python制作二维码
			python-qrcode是个用来生成二维码图片的第三方模块,主要依赖的是 PIL 模块和 qrcode 库.(PIL模块只支持python2.7及以下版本,python3之后无法使用,官方推荐pyt ... 
- PopupMenu-使用实例跟监听事件
			今天需要给一个控件添加弹出菜单功能.就顺便学习了下popupMenu的使用,记录下来. 它的使用其实也非常的简单,看如下代码 popupMenu = new PopupMenu(MainActivit ... 
- 漫漫人生路-学点Jakarta基础-Java8新特性 Stream/Lambda
			背景 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利.高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk dat ... 
- es6 --- var  const   let
			var const let 区别 今天第一次遇到const定义的变量,查阅了相关资料整理了这篇文章.主要内容是:js中三种定义变量的方式const, var, let的区别. 1. const ... 
- flume中sink到hdfs,文件系统频繁产生文件和出现乱码,文件滚动配置不起作用?
			问题描述 解决办法 先把这个hdfs目录下的数据删除.并修改配置文件flume-conf.properties,重新采集. # Licensed to the Apache Software Fou ... 
- Elasticsearch之源码分析(shard分片规则)
			前期博客是 Elasticsearch之源码编译 (1)elasticsearch在建立索引时,根据id或(id,类型)进行hash,得到hash值之后再与该索引的分片数量取模,取模的值即为存入的分片 ... 
- 洛谷P1439 最长公共子序列(LCS问题)
			题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子 ... 
- 网上看到的一些IT资源
			A.网站模板+logo+服务器主机+发票生成 HTML5 UP:响应式的HTML5和CSS3网站模板. Bootswatch:免费的Bootstrap主题. Templated:收集了845个免费的C ... 
- DG archive gap
			什么是archive gap Archive Gap就是standby端日志应用的过程中丢失的一段范围的redo.典型的发生在standby端不能接收primary的redo信息或者接收后不能应用这些 ... 
- SQL、Linq相关字段搜索
			结合一些分词组件,如盘古,对于用户查询关键字红按钮很容易分出 ‘红’ ‘按钮’二个单词 我们假设产品名称列里面是红色,规格里面是按钮 /* 普通sql实现全文搜索declare @key1 nvarc ... 
