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. 使用canvas编写时间轴插件

    使用canvas编写时间轴插件 背景 项目中有一个视频广场的功能,需要一个时间轴类似视频播放中进度条功能一样显示录像情况,并且可以点击.拖动.放大缩小展示时间轴,获取到时间轴的某个时间.原来的时间轴是 ...

  2. 《android开发艺术探索》读书笔记(六)--Drawable

    接上篇<android开发艺术探索>读书笔记(五)--RemoteViews [BitmapDrawable] 简单的图片 <!xml version="1.0" ...

  3. UVA - 1371 Period 二分+dp

    思路:设字符串x的长度为n,y的长度为m,那么答案一定在[0, m]之间,那么可以二分求答案. d(i, j)表示第一个串前i个字符至少需要经过多少次才能的到第二个串的前j个字符,转移方程d(i, j ...

  4. Ubuntu17.10下启动Rancher

    1.安装Docker: 获取最新的docker安装包 wget -qO- https://get.docker.com/ | sh 2.启动docker后台服务: service docker sta ...

  5. ES磁盘分配不均问题

    最近es集群磁盘空间告警,日志又没地方可以迁移,然后申请了新的服务器,一次性加入8台新的服务器 新增了32个新的数据节点,至此,我们的主集群已经到达85个数据节点的规模,整个集群数据已达到PB级别,终 ...

  6. 禁掉coolie,session还能正常使用吗?

    Cookie禁用了,Session还能用吗?   Cookie与 Session,一般认为是两个独立的东西,Session采用的是在服务器端保持状态的方案,而Cookie采用的是在客户端保持状态的方案 ...

  7. Java 多线程入门

    进程与线程 在学习Java多线程之前,先简单复习一下进程与线程的知识. 进程:进程是系统进行资源分配和调度的基本单位,可以将进程理解为一个正在执行的程序,比如一款游戏. 线程:线程是程序执行的最小单位 ...

  8. apue.h头文件(UNIX环境高级编程)

    在看UNIX环境高级编程是,碰到一个头文件"apue.h",搜一下别人的帖子,其实apue.h是作者自己写的一个文件,包含了常用的头文件,系统不自带.其中包含了常用的头文件,以及出 ...

  9. dojo报错总结

    dojo报错总结 1.错误一 neteaseTracker is not defined dojo.js(第15行) 2.错误二 _10 is undefined _SearchMixin.js(第5 ...

  10. PHP stream_context_create()作用和用法分析

    stream_content_create 创建并返回一个文本数据流并应用各种选项,可用于fopen(),filegetcontents()等过程的超时设置.代理服务器.请求方式.头信息设置的特殊过程 ...