java中,启动线程通常是通过Thread或其子类通过调用start()方法启动。
 常见使用线程有两种:实现Runnable接口和继承Thread。而继承Thread亦或使用TimerTask其底层依旧是实现了Runnabel接口。考虑到java的单继承的限制,所以在开发过程中大部分情况在使用线程的时候是通过实现Runnabel接口或者Runnbel匿名类来实现的。
 例如:

package com.zpj.thread.blogTest;
/**
* Created by PerkinsZhu on 2017/8/11 16:42.
*/
public class ThreadTest { public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
//所有的这些启动方式的执行体都是在run方法中完成的
threadTest.testLambda();
threadTest.testRunnableWithAnonymousRunnable();
threadTest.testRunnableWithAnonymousThread();
threadTest.testRunnable();
threadTest.testMyThread();
} public void testLambda() {//lambda表达式开启线程 jdk1.8中的特性
new Thread(() -> System.out.println("i am lambda Thread....")).start();
} public void testRunnableWithAnonymousThread() {//匿名Thread类开启线程
new Thread() {
@Override
public void run() {
System.out.println("i am ThreadWithAnoymous");
}
}.start();
} public void testRunnableWithAnonymousRunnable() {//匿名Runnable类开启线程
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("i am RunableWithAnoymous");
}
});
thread.start();
} public void testRunnable() {//实现Runnable接口
MyRunnable runable = new MyRunnable();
Thread thread = new Thread(runable);
thread.start();
} public void testMyThread() {//继承自Thread
MyThread thread = new MyThread();
thread.setName("MyThread");
thread.start();
}
} class MyRunnable implements Runnable {//实现Runnable接口 @Override
public void run() {
System.out.println("i am MyRunnable");
}
} class MyThread extends Thread {//继承Thread @Override
public void run() {
System.out.println(" i am MyThread!!");
}
}

注意,直接调用run()方法的方式执行线程体并未开启新线程,只是在main方法中调用了一个普通方法而已。而使用start()方法则会开启一个新的线程执行。两者的区别主要表现在前者是阻塞式的,而后者为非阻塞式。

例如:

    public void testStartAndRun(){
MyThread thread = new MyThread();
thread.setName("MyThread");
thread.start();//start启动两者异步非阻塞运行
while (true){
System.out.println("---- "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyThread extends Thread {//继承Thread @Override
public void run() {
while(true){
System.out.println("=== "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

运行结果如下:

---- main
==== MyThread
---- main
==== MyThread
==== MyThread
---- main
==== MyThread
---- main

而把thread.start() 修改为thread.run();之后,则如下

==== main
==== main
==== main
==== main
==== main
==== main

这里之所以线程名称为main是因为是在main线程中调用的run方法,所以打印出来的是===main。而thread.run();语句下面的循环则永远不会执行,程序将会一直在run方法中循环下去。

那么调用start方法,程序都做了些什么呢?看一下底层实现。

    public synchronized void start() {
//验证线程的状态
if (threadStatus != 0) {//这里的验证涉及到线程不能重复启动的问题,线程多次调用start则会抛出该异常
throw new IllegalThreadStateException();
}
//把该线程加入到线程组中
group.add(this);
boolean started = false;//标识线程是否启动成功
try {
start0();//调用native方法启动线程 该方法是阻塞的,程序等待其完成之后执行下面语句如果执行失败则直接抛出异常进入finally。
started = true;//修改线程启动状态
} finally {
try {
if (!started) {//启动失败,则移出线程组
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
}
}
} private native void start0();//native方法启动线程

通过Runnable启动具有一定的局限,执行线程没有返回值,无法捕获异常。在有些特殊情况下需要线程返回结果的时候就不太合适。这时可以选择Callable接口来完成。Callable涉及到Future模型,这到后面再说。

=============================================

原文链接:多线程(三) java中线程的简单使用 转载请注明出处!

=============================================

-----end

多线程(三) java中线程的简单使用的更多相关文章

  1. Java中线程的使用 (2)-多线程、线程优先级、线程睡眠、让步、阻塞

    Java中线程的使用 (2)-多线程.线程优先级.线程睡眠.让步.阻塞 (一)多线程使用方法 说明:创建每个新的线程,一定要记得启动每个新的线程(调用.start()方法) class Xc3 ext ...

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

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

  3. 沉淀再出发:java中线程池解析

    沉淀再出发:java中线程池解析 一.前言 在多线程执行的环境之中,如果线程执行的时间短但是启动的线程又非常多,线程运转的时间基本上浪费在了创建和销毁上面,因此有没有一种方式能够让一个线程执行完自己的 ...

  4. 面试官:Java中线程是按什么顺序执行的?

    摘要:Java中多线程并发的执行顺序历来是面试中的重点,掌握Java中线程的执行顺序不仅能够在面试中让你脱颖而出,更能够让你在平时的工作中,迅速定位由于多线程并发问题导致的"诡异" ...

  5. java中线程机制

    java中线程机制,一开始我们都用的单线程.现在接触到多线程了. 多线性首先要解决的问题是:创建线程,怎么创建线程的问题: 1.线程的创建: 四种常用的实现方法 1.继承Thread. Thread是 ...

  6. 多线程(五) java的线程锁

    在多线程中,每个线程的执行顺序,是无法预测不可控制的,那么在对数据进行读写的时候便存在由于读写顺序多乱而造成数据混乱错误的可能性.那么如何控制,每个线程对于数据的读写顺序呢?这里就涉及到线程锁. 什么 ...

  7. Java中线程池,你真的会用吗?

    在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Executors静态工厂构建线程池,但一般不建 ...

  8. Java中线程和线程池

    Java中开启多线程的三种方式 1.通过继承Thread实现 public class ThreadDemo extends Thread{ public void run(){ System.out ...

  9. Java中线程池,你真的会用吗?ExecutorService ThreadPoolExcutor

    原文:https://www.hollischuang.com/archives/2888 在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及 ...

随机推荐

  1. Bootstrap表单验证

    主要用过两个: jqBootstrapValidation: https://github.com/ReactiveRaven/jqBootstrapValidation bootstrapValid ...

  2. Dubbo广播模式下报错:Can't assign requested address解决办法

    原因: 尝试使用Dubbo的multicast模式,发现一运行就报Can't assign requested address的错误,造成这种原因的主要是系统中开启了IPV6协议(比如window7) ...

  3. Hibernate学习(二)保存数据

    package cn.lonecloud.test; import java.util.Date; import org.hibernate.HibernateException; import or ...

  4. EmguCv“线段” 结构类型学习

    1. 文件所在 Namespace: Emgu.CV.Structure Assembly: Emgu.CV (in Emgu.CV.dll) Version: 3.0.0.2157 (3.0.0.2 ...

  5. Spring / Hibernate 应用性能调优

    来源:ImportNew - 陈晓舜 对大部分典型的Spring/Hibernate企业应用来说,应用的性能大部分由持久层的性能决定. 这篇文章会重温一下怎么去确认我们的应用是否是”数据库依赖(dat ...

  6. 快了快了,你的 MacBook Pro 和 FineUICore!

    着玻璃窗,看到星巴克里那帮人拿着MacBook喝咖啡,你是不是要默念一遍:这帮傻叉,就爱装逼! 不过话说回来,你想不想尝试下这个傻叉的感觉? 是时候了,给自己一个理由,拥有自己的 MacBook Pr ...

  7. linux nginx常见问题及优化,压力测试,tomcat服务器优化

    nginx常见问题 nginx优化全局配置优化[root@web2 nginx]# vim conf/nginx.confuser nobody;worker_processes 1;(与cpu核心数 ...

  8. Davinci DM6446开发攻略——DSP开发工程建立

    前段时间一直忙一个项目,同时在生活上时时提防和抵抗中国地沟油.国外核心转基因调和油.大豆油.色拉油.大米玉米.可怕的喂药鱼.药水泡农药喷无虫咬的青菜,所以没时间打理自己的博客,让开发攻略停顿了一段时间 ...

  9. Sparklyr与Docker的推荐系统实战

    作者:Harry Zhu 链接:https://zhuanlan.zhihu.com/p/21574497 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 相关内容: ...

  10. Hi3531添加16GByte(128Gbit) NAND Flash支持

    0.板子上已有Nor Flash了,添加的Nand Flash型号为MT29F128G08CJABAWP,进系统挂接NAND作为一个分区 1.修改uboot u-boot-2010.06/driver ...