java线程的创建有两种方式,这里我们通过简单的实例来学习一下。一切都明明白白,但我们仍匆匆错过,因为你相信命运,因为我怀疑生活。

java中多线程的创建

一、通过继承Thread类来创建多线程

public class HelloThread extends Thread {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println("Hello from a thread!");
} catch (InterruptedException e) {
e.printStackTrace();
}
} public static void main(String[] args) throws InterruptedException {
HelloThread helloThread = new HelloThread();
helloThread.start();
System.out.println("In main thread.");
}
}

运行的结果如下:

In main thread.
Hello from a thread!

我们这里对Thread类的start的方法做一些说明,官方文档的说明:

Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).
It is never legal(合法) to start a thread more than once(不止一次). In particular, a thread may not be restarted once it has completed execution. Throws:
IllegalThreadStateException - if the thread was already started

我们在上述例子的基础上,对上述的说明做一个代码的测试。在helloThread.start();代码的后面添加代码:

System.out.println(helloThread.getName());
helloThread.start();

一次的运行结果如下所示,在添加代码的第二行(helloThread.start();)报的错误。

Exception in thread "main" java.lang.IllegalThreadStateException
Thread-
at java.lang.Thread.start(Thread.java:)
at com.linux.huhx.thread.HelloThread.main(HelloThread.java:)
Hello from a thread!

如果在添加helloThread.start();之前让主线程睡眠3秒,也就是让先启动的helloThread线程执行完毕。我们再调用helloThread.start()启动线程。

TimeUnit.SECONDS.sleep();
System.out.println(helloThread.getName());
helloThread.start();

运行的结果如下:

Hello from a thread!
Thread-
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:)
at com.linux.huhx.thread.HelloThread.main(HelloThread.java:)

二、通过实现Runnable接口来创建多线程

public class HelloRunnable implements Runnable {

    @Override
public void run() {
try {
System.out.println("Hello from a thread!");
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
Thread thread = new Thread(new HelloRunnable());
thread.start();
System.out.println("In main method.");
}
}

运行的结果如下:

In main method.
Hello from a thread!

  这种使用实现HelloRunnable接口的方式是比较推崇的,因为java类中只能单继承可以多实现。现在看一下它的简单原理new Thread(new HelloRunnable())的源码如下:

public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}

init的方法是初始化线程的一些信息:

private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) {
if (name == null) {
throw new NullPointerException("name cannot be null");
} this.name = name; Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
if (security != null) {
g = security.getThreadGroup();
} if (g == null) {
g = parent.getThreadGroup();
}
} g.checkAccess(); if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
} g.addUnstarted(); this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext = acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
this.stackSize = stackSize;
tid = nextThreadID();
}

  最重要的一行代码就是this.target = target;设置了线程target为我们的Runnable对象。我们都知道thread.start()启动一个线程,实际是调用线程的run方法。现在我们看一下Thread类的run方法。

@Override
public void run() {
if (target != null) {
target.run();
}
}

  可以看到是调用了target的run方法,在我们这里就是(HelloRunnable)。对于继承Thread的的情况来说,就拿上述的HelloThread来讲,它里面的target是空的。不过执行的run方法是HelloThread重写的run方法。所以不存在HelloThread中没有target就不会执行的情况。

友情链接

java基础---->多线程之Runnable(一)的更多相关文章

  1. java基础---->多线程之synchronized(六)

    这里学习一下java多线程中的关于synchronized的用法.我来不及认真地年轻,待明白过来时,只能选择认真地老去. synchronized的简单实例 一. synchronized在方法上的使 ...

  2. java基础---->多线程之ThreadLocal(七)

    这里学习一下java多线程中的关于ThreadLocal的用法.人时已尽,人世还长,我在中间,应该休息. ThreadLocal的简单实例 一.ThreadLocal的简单使用 package com ...

  3. java基础---->多线程之wait和notify(八)

    这里学习一下java多线程中的关于wait方法和notify方法的用法.命运不是风,来回吹,命运是大地,走到哪你都在命运中. wait和notify方法的使用 一.wait与notify的简单实例 i ...

  4. java基础---->多线程之interrupt(九)

    这里我们通过实例来学习一下java多线程中关于interrupt方法的一些知识.执者失之.我想当一个诗人的时候,我就失去了诗,我想当一个人的时候,我就失去了我自己.在你什么也不想要的时候,一切如期而来 ...

  5. java基础---->多线程之yield(三)

    yield方法的作用是放弃当前的CPU资源,将它让给其它的任务去占用CPU执行时间.但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片.今天我们通过实例来学习一下yield()方法的使用.最是 ...

  6. java基础---->多线程之Daemon(五)

    在java线程中有两种线程,一种是用户线程,另一种是守护线程.守护线程是一种特殊的线程,当进程中不存在非守护线程了,则守护线程自动销毁.今天我们通过实例来学习一下java中关于守护线程的知识.我是个平 ...

  7. java基础---->多线程之priority(四)

    线程的priority能告诉调度程序其重要性如何,今天我们通过实例来学习一下java多线程中的关于优先级的知识.我从没被谁知道,所以也没被谁忘记.在别人的回忆中生活,并不是我的目的. java多线程的 ...

  8. Java多线程之Runnable与Thread

    Java多线程之Thread与Runnable 一.Thread VS Runnable 在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类和 ...

  9. Java基础之线程——使用Runnable接口(JumbleNames)

    控制台程序. 除了定义Thread新的子类外,还可以在类中实现Runnable接口.您会发现这比从Thread类派生子类更方便,因为在实现Runnable接口时可以从不是Thread的类派生子类,并且 ...

随机推荐

  1. 抽取、转换和装载介绍(七)管理ETL环境(待续)

    数据仓库的目标之一是能够为增强业务功能提供适时的.一致的和可靠的数据. 为了达到上述目标,ETL必须按照下述三条标准不断地加以完善: 可靠性 可用性 易管理性 子系统22--作业调度器 子系统23-- ...

  2. RTMP流媒体播放过程:握手,建立连接,建立流,播放

    本文讲述从打开一个RTMP流媒体到视音频数据开始播放的整个过程. 播放一个流媒体有两个前提步骤: 第一步,建立一个网络连接(NetConnection): 第二步,建立一个网络流(NetStream) ...

  3. 超多的CSS3圆角渐变网页按钮

    <!DOCTYPE html><head><title>超多的CSS3圆角渐变按钮</title><style type="text/c ...

  4. MySQL 常用语法 之 DISTINCT

    DISTINCT作用很简单就是去除重复行的数据. 具体看下面列子 表A数据[两条 nami 99] nameA   scoreA robin    98 nami    99 saber  98 lu ...

  5. e674. 创建并绘制加速图像

    Images in accelerated memory are much faster to draw on the screen. This example demonstrates how to ...

  6. PhoneGap开发不可或缺的五件装备

    PhoneGap是一种介于WebApp和NativeApp之间的解决方案,它为每种移动客户端提供一个Native的壳,这种壳里边包着一个Web应 用.借助于壳,Web应用可以被安装,可以被发布到各大市 ...

  7. MJRefresh原理分析

    MJRefresh是流行的下拉刷新控件.前段时间为了修复一个BUG.读了它的源代码.本文总结一下实现的原理 下拉刷新的基本原理 大部分的下拉刷新控件.都是用contentInset实现的.默认情况下. ...

  8. Linux基础回想(1)——Linux系统概述

    1. 什么是操作系统?它与硬件以及其它软件之间的关系是如何的? 操作系统是控制和管理计算机系统内各种硬件和软件资源.有效组织多道程序执行的系统软件(或程序集合),是用户和计算机之间的接口.详细的说: ...

  9. Pacbio 纯三代组装复活草基因组

    对于植物等真核生物基因组来说,重复序列, 多倍体,高杂合度等特征在利用二代数据进行组装的时候都会有很大的问题: 利用二代数据组装出来的基因组,大多达不到完成图的水准,通常只是覆盖到编码蛋白的基因区域, ...

  10. 【Java面试题】9 abstract class和interface有什么区别?

    含有abstract修饰符的class即为抽象类,abstract 类不能创建的实例对象.含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必 ...