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. 通过buildroot 移植 libsocketcan.so 以及 can 工具

    进入buildroot make menuconfig Target packages ---> Networking applications ---> [*] can-utils // ...

  2. am335x Linux kernel DTS pinmux 定义记录

    记录am335x TI PDK3.0 Linux Kernel 设备的pinmux 的配置 在TI 的Linux kernel 设备树里面,有很多关于pinctrl-single,pins 的配置, ...

  3. [MMC]Linux MMC/SD/SDIO驱动分析

    转自:http://www.cnblogs.com/cslunatic/p/3678045.html 一.SD/MMC/SDIO概念区分 SD(SecureDigital)与 MMC(Multimed ...

  4. 腾讯云 Linux 挂载数据盘

            查看已挂载的硬盘   1) 运行fdisk -l命令查看硬盘信息.   硬盘从未进行初始化时,需要先创建文件系统,       硬盘格式化   运行mkfs.ext4 device_n ...

  5. 如何查看机器是否为vmware虚拟机

    vmware虚拟机的网卡MAC地址一般都是005056开头的,可用ifconfig看一下,也可用dmesg |grep vm查看 艺搜参考 http://bbs.chinaunix.net/threa ...

  6. 【转】JS函数集合大全

    1.document.write(""); 输出语句 2.JS中的注释为// 3.传统的HTML文档顺序是:document->html->(head,body) 4. ...

  7. ioc和aop的区别?

    ioc:控制反转(Inversion of Control,英文缩写为IoC)把创建对象的权利交给框架,是框架的重要特征,并非面向对象编程的专用术语.它包括依赖注入(Dependency Inject ...

  8. (转) 打开声音设备需要使用waveOutOpen函数

    转自:http://blog.csdn.net/nokianasty/article/details/8558151 打开声音设备 打开声音设备需要使用waveOutOpen函数(可以在您的文档中查到 ...

  9. 双卡手机怎么指定SIM卡打电话

    双卡手机如何指定SIM卡打电话 package com.example.dualsimtest; import android.app.Activity; import android.content ...

  10. centos 6.5配置samba

    Samba简介 Samba是一个能让Linux系统应用Microsoft网络通讯协议的软件,而SMB是Server Message Block的缩写,即为服务器消息块 ,SMB主要是作为Microso ...