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. Spring-Security 自定义Filter完成验证码校验

    Spring-Security的功能主要是由一堆Filter构成过滤器链来实现,每个Filter都会完成自己的一部分工作.我今天要做的是对UsernamePasswordAuthenticationF ...

  2. python爬虫提取冰与火之歌五季的种子

    # -*- encoding:utf-8 -*- import requests import re import sys reload(sys) sys.setdefaultencoding(&qu ...

  3. HDU5992 - Finding Hotels

    原题链接 Description 给出个二维平面上的点,每个点有权值.次询问,求所有权值小于等于的点中,距离坐标的欧几里得距离最小的点.如果有多个满足条件的点,输出最靠前的一个. Solution 拿 ...

  4. 有状态InheritableThreadLocal 配合 JDK8 ,异步方法调用

    我们可以把一个类的作用域注解为 @Scope(scopeName = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode. ...

  5. java 集合框架(三)Collection

    一.概述 Collection是集合框架的根接口.不同的集合具有不同的特性,比如有的集合可以有重复元素,有的不可以,有的可以排序,有的不可排序,如此等等,而Collection作为集合的根接口,它规范 ...

  6. js将汉字转为相应的拼音

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  7. R语言︱XGBoost极端梯度上升以及forecastxgb(预测)+xgboost(回归)双案例解读

    XGBoost不仅仅可以用来做分类还可以做时间序列方面的预测,而且已经有人做的很好,可以见最后的案例. 应用一:XGBoost用来做预测 ------------------------------- ...

  8. R语言之内存管理

    转载于:http://blog.csdn.net/hubifeng/article/details/41113789 在处理大型数据过程中,R语言的内存管理就显得十分重要,以下介绍几种常用的处理方法. ...

  9. offline页面开发常用方法及页面控件验证

    offline页面开发常用方法及页面控件验证,对一些CheckBoxList操作进行封装,新人可以直接使用该代码. 1.返回上一页网址 /// <summary> /// Descript ...

  10. Parse Fatal Error at line 41 column 24: 元素类型 "url-pattern" 必须由匹配的结束标记 "</url-pattern>" 终止

    1.错误描述 严重: Parse Fatal Error at line 41 column 24: 元素类型 "url-pattern" 必须由匹配的结束标记 "< ...