Java多线程 之 Runnable Thread (一)

原创 2016年06月01日 09:43:33

最近看的东西有些乱。励志从XOA2看起、学起,发现需要看下thrift,看着看着thrift,发现需要学学NIO,学完了NIO温习温习前面看的thrift,却要休假10天。休假回来,感觉要学学多线程。多线程这厮,看《Thinking in java》第21章的前几个小节,这是第3次了。这次要坚持下来,并且记录下来。——勉之!
程序做的事情可以抽象成一个一个“任务”,任务是由线程来驱动的,线程是一个进程中单一的顺序控制流。在java中用什么来定义任务呢?

1.Runnable

在java中可以通过实现Runnable接口来定义一个任务。如:

package org.fan.learn.thread.task;
/**
 * Created by fan on 16-5-25.
 */
public class LiftOff implements Runnable {
    private static int taskCunnt = 0;
    private final int id = taskCunnt++;
    private int countDown = 10;
    private void status() {
        System.out.print("Task(" + id + ")#" + (countDown > 0 ? countDown : "liftOff") + "   ");
    }
    public void run() {
        while (countDown-- > 0) {
            status();
            Thread.yield();
        }
    }
}
package org.fan.learn.thread.simple;
import org.fan.learn.thread.task.LiftOff;
/**
 * Created by fan on 16-5-31.
 */
public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            new LiftOff().run();
        }

    }
}

程序的执行结果如下所示:
Task(0)#9 Task(0)#8 Task(0)#7 Task(0)#6 Task(0)#5 Task(0)#4 Task(0)#3 Task(0)#2 Task(0)#1 Task(0)#liftOff Task(1)#9 Task(1)#8 Task(1)#7 Task(1)#6 Task(1)#5 Task(1)#4 Task(1)#3 Task(1)#2 Task(1)#1 Task(1)#liftOff Task(2)#9 Task(2)#8 Task(2)#7 Task(2)#6 Task(2)#5 Task(2)#4 Task(2)#3 Task(2)#2 Task(2)#1 Task(2)#liftOff Task(3)#9 Task(3)#8 Task(3)#7 Task(3)#6 Task(3)#5 Task(3)#4 Task(3)#3 Task(3)#2 Task(3)#1 Task(3)#liftOff Task(4)#9 Task(4)#8 Task(4)#7 Task(4)#6 Task(4)#5 Task(4)#4 Task(4)#3 Task(4)#2 Task(4)#1 Task(4)#liftOff
这里直接调用了Runnable接口的run方法。注意这个run方法是没有任何返回值的。因此无法直到任务执行的状态返回值。但是驱动任务时很少这么写,一般都是由线程来驱动任务。

Thread

package org.fan.learn.thread.simple;
import org.fan.learn.thread.task.LiftOff;
/**
 * Created by fan on 16-5-31.
 */
public class Main2 {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            new Thread(new LiftOff()).start();
        }
        System.out.println("Waiting for liftOff!");
    }
}

程序执行结果如下所示:
Task(0)#9 Task(1)#9 Task(0)#8 Task(1)#8 Task(0)#7 Task(1)#7 Task(0)#6 Task(1)#6 Task(0)#5 Task(1)#5 Task(0)#4 Task(1)#4 Task(0)#3 Task(1)#3 Task(0)#2 Task(1)#2 Task(0)#1 Task(1)#1 Task(0)#liftOff Task(1)#liftOff Task(2)#9 Task(2)#8 Waiting for liftOff!
Task(2)#7 Task(3)#9 Task(2)#6 Task(3)#8 Task(2)#5 Task(3)#7 Task(4)#9 Task(3)#6 Task(2)#4 Task(3)#5 Task(4)#8 Task(3)#4 Task(2)#3 Task(3)#3 Task(4)#7 Task(3)#2 Task(2)#2 Task(3)#1 Task(4)#6 Task(3)#liftOff Task(2)#1 Task(4)#5 Task(2)#liftOff Task(4)#4 Task(4)#3 Task(4)#2 Task(4)#1 Task(4)#liftOff
Process finished with exit code 0

注意
(1)上面调用的是Thread.start()。start方法会为线程的执行做一些准备工作,然后调用Runnable接口的run方法。
(2)可以看到main中先输出了“Waiting for liftOff”方法,后面还有线程在执行。说明在main中执行完输出退出程序时,new出的Thread对象依然还在内存中,没有被垃圾回收,依然可以继续执行,直到其run方法执行完。其实,每个Thread“注册”了自己,因此JVM中确实有一个对它的引用,所以在main退出后,没有被垃圾回收。Thread对象有别于普通对象。

run与start的区别

run方法不会启动新的线程,在调用run方法的线程中运行。
而start方法会new出一个新线程,在这个新线程中执行。
这也就是为什么需要区分“线程”和“任务”这两个概念。线程是为了驱动任务的。可以这么说,任务是一个静态的概念,而线程是一个动态的概念。
下面有个例子(该例子来自网络):

// Demo.java 的源码
class MyThread extends Thread{  
    public MyThread(String name) {
        super(name);
    }

    public void run(){
        System.out.println(Thread.currentThread().getName()+" is running");
    } 
}; 

public class Demo {  
    public static void main(String[] args) {  
        Thread mythread=new MyThread("mythread");

        System.out.println(Thread.currentThread().getName()+" call mythread.run()");
        mythread.run();

        System.out.println(Thread.currentThread().getName()+" call mythread.start()");
        mythread.start();
    }  
}

运行结果:

main call mythread.run()
main is running
main call mythread.start()
mythread is running

(01) Thread.currentThread().getName()是用于获取“当前线程”的名字。当前线程是指正在cpu中调度执行的线程。
(02) mythread.run()是在“主线程main”中调用的,该run()方法直接运行在“主线程main”上。
(03) mythread.start()会启动“线程mythread”,“线程mythread”启动之后,会调用run()方法;此时的run()方法是运行在“线程mythread”上。

版权声明:本文为博主原创文章,未经博主允许不得转载。

【Java并发编程】之六:Runnable和Thread实现多线程的区别(含代码)

Java中实现多线程有两种方法:继承Thread类、实现Runnable接口,在程序开发中只要是多线程,肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下...
  • mmc_maodun
  • mmc_maodun
  • 2013年12月06日 10:15
  • 37092

JAVA多线程之Runnable和Thread比较

在我们开发的过程中常常会碰到多线程的问题,对于多线程的实现方式主要有两种:实现Runnable接口、继承Thread类。对于这两种多线程的实现方式也是有着一些差异。既然实现了多线程那必然离不开管理这些...
  • u013755987
  • u013755987
  • 2016年07月11日 21:15
  • 8578

Java多线程之 Thread VS Runnable 【带案例】

为此,我们举个例子,假设有火车站有三个窗口,在卖火车票,总共只有5张票。每一个线程相当于一个窗口,分别售票 package com.thread; class myThread extends T...
  • uniquewonderq
  • uniquewonderq
  • 2015年08月31日 18:33
  • 1144

java线程系列---Runnable和Thread的区别、线程同步

Runnable和Thread的区别原文 线程锁原文 鉴于我这篇文章被鄙视了,哈哈哈哈。我决定整理一下资源共享线程同步相关的知识。欢迎鄙视并谈一谈见解。 Java传统多线程的...
  • guoxiaolongonly
  • guoxiaolongonly
  • 2016年02月22日 16:19
  • 2723

JAVA——多线程编程之两种多线程方法:继承Thread类和实现Runnable接口(一)

【1】了解进程与线程的概念 进程是一个程序在其自身的地址空间中执行一次活动,是资源申请、调度和独立运行的单位。 线程是进程中的一个单一的连续控制流程,一个进程可以包含一个或多个线程。 如果要在一个程序...
  • jingzi123456789
  • jingzi123456789
  • 2017年04月09日 21:18
  • 503

java 创建线程的三种方法Callable,Runnable,Thread比较及用法

编写多线程程序是为了实现多任务的并发执行,从而能够更好地与用户交互。一般有三种方法,Thread,Runnable,Callable.   Runnable和Callable的区别是, ...
  • z69183787
  • z69183787
  • 2014年06月05日 14:59
  • 1156

Runnable接口与Thread类的区别

什么时候让线程实现Runnable接口,什么时候让线程继承Thread类? JDK帮助文档中的原话:Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现 (不明白是啥意思) 孙鑫...
  • colder2008
  • colder2008
  • 2013年12月27日 17:35
  • 1541

Java 多线程实现接口Runnable和继承Thread区别

Java中有两种实现多线程的方式。一是直接继承Thread类,二是实现Runnable接口。那么这两种实现多线程的方式在应用上有什么区别呢?           为了回答这个问题,我们可以通过编写一...
  • LVXIANGAN
  • LVXIANGAN
  • 2016年09月30日 10:07
  • 2903

多线程——Java中继承Thread类与实现Runnable接口的区别

线程我只写过继承Thread类的,后来知道java多线程有三种方式,今天首先比较一下常用的继承Thread类和实现Runnable接口的区别。               按着Ctrl键进入Threa...
  • xdd19910505
  • xdd19910505
  • 2016年02月24日 18:27
  • 5556

Java多线程-(4)线程的创建、启动、Runnable和Thread

一、定义线程 在Java中,多线程的实现有两种方式: 1、扩展java.lang.Thread类 2、实现java.lang.Runnable接口 二、实例化线...
  • u011936381
  • u011936381
  • 2013年12月21日 17:01
  • 2337
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java多线程 之 Runnable Thread (一)
举报原因:
原因补充:

(最多只允许输入30个字)