thread和runnable区别和thread哪个好

博客分类:
我们都晓得java实现线程2种方式,一个是继承Thread,另一个是实现Runnable。
模拟窗口买票,第一例子继承thread,代码如下
public class ThreadTest {
public static void main(String[] args) {
Thread1 t1 = new Thread1("01");
Thread1 t2 = new Thread1("03");
t1.start();
t2.start();
//可以看出一共卖了200张票
class Thread1 extends Thread{
private int ticket = 100;
public Thread1(String name)
super(name);
public void run() {
while(ticket & 0)
System.out.println("窗口:"+Thread.currentThread().getName()+",卖了1个,剩余:"+(ticket--));
模拟窗口买票,实现Runnable接口,代码如下
public class RunnableTest {
public static void main(String[] args) {
Runnable1 r1 = new Runnable1();
new Thread(r1, "01").start();
new Thread(r1, "03").start();
//2个窗口一共卖了100张
class Runnable1 implements Runnable
private int ticket = 100;
public void run() {
while(ticket & 0)
System.out.println("窗口:"+Thread.currentThread().getName()+",卖了1个,剩余:"+(ticket--));
通过上面代码运行我们可以得到如下结论:
1.Thread和Runnable都可以实现多线程(废话)
2.Thread是类,而Runnable是接口,这就是类和接口区别,类只能继承一次,而接口可以实现多个接口。
3.Thread实现Runnable接口,这个可以查看Thread的源代码。
4.最重要的分享资源功能,一般我们使用多线程就是快速解决资源问题。Runnable可以实现资源分享,类实现Runnable并不具备线程功能,必须通过new Thread(runabble子类)调用start()启动线程,所以我们通常new一个runnable的子类,启动多个线程解决资源问题。Thread是类所以我们每次new一个对象时候资源已经实例化了,不能资源共享,Thread类要实现资源共享,可以声明变量为static,类共享的可以解决。
5.通过以上建议最好实现Runnable接口 实现多线程。
欢迎交流企鹅群:
30 顶17 踩
两个线程存在数据竞争,尽然不用锁?肯定要用,这只是写的测试案例而已
Thread t = new Thread1(); Thread t1 = new Thread(t,"01");& Thread t2 = new Thread(t,"03");& t1.start();& t2.start();& 这样写就能共享了,实际上和Runnable没什么区别。是的,可以的
浏览: 33430 次
来自: 南京
&div class=&quote_title ...
你这三段代码根本就没可比性。
不错哦 给个赞
zx_code 写道郑州蘑菇云 写道为什么必须要加入呢?直接使 ...
郑州蘑菇云 写道为什么必须要加入呢?直接使用&mvc:a ...博客分类:
继承Thread实现多线程:
//MyThread类
class MyThread extends Thread{
public MyThread(String name) {
this.name =
public void run(){
for(int i=0;i&10;i++){
System.out.println("线程开始:"+this.name+",i="+i);
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("线程出错"+this.name);
//ThreadDemo类
public class ThreadDemo {
public static void main(String[] args) {
MyThread mt1=new MyThread("线程a");
MyThread mt2=new MyThread("线程b");
mt1.run();
mt2.run();
此时实例化MyThread类,调用的是run()方法,此时执行的结果如下图:
此时结果很有规律,先第一个对象执行,然后第二个对象执行,并没有相互运行。在JDK的文档中可以发现,一旦调用start()方法,则会通过JVM找到run()方法。下面启动start()方法启动线程:
//ThreadDemo类
public class ThreadDemo {
public static void main(String[] args) {
MyThread mt1=new MyThread("线程a");
MyThread mt2=new MyThread("线程b");
mt1.start();
mt2.start();
这样程序可以正常完成交互式运行。那么为啥非要使用start();方法启动多线程呢?
在JDK的安装路径下,src.zip是全部的java源程序,通过此代码找到Thread中的start()方法的定义,可以发现此方法中使用了private native void start0();其中native关键字表示可以调用操作系统的底层函数,那么这样的技术成为JNI技术(java Native Interface)。
Runnable接口:
在实际开发中一个多线程的操作很少使用Thread类,而是通过Runnable接口完成。
//MyThread类
class MyThread implements Runnable{
public MyThread(String name) {
this.name =
public void run(){
for(int i=0;i&10;i++){
System.out.println("线程开始:"+this.name+",i="+i);
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("线程出错"+this.name);
但是在使用Runnable定义的子类中没有start()方法,只有Thread类中才有。此时观察Thread类,有一个构造方法:public Thread(Runnable targer)此构造方法接受Runnable的子类实例,也就是说可以通过Thread类来启动Runnable实现的多线程。(start()可以协调系统的资源):
public class ThreadDemo {
public static void main(String[] args) {
MyThread mt1=new MyThread("线程a");
MyThread mt2=new MyThread("线程b");
new Thread(mt1).start();
new Thread(mt2).start();
两种实现方式的区别和联系:
在程序开发中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下好处:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。
以卖票程序为例,通过Thread类完成:
class MyThread extends Thread{
private int ticket=10;
public void run(){
for(int i=0;i&20;i++){
if(this.ticket&0){
System.out.println("卖票:ticket"+this.ticket--);
下面通过三个线程对象,同时卖票:
public class ThreadTicket {
public static void main(String[] args) {
MyThread mt1=new MyThread();
MyThread mt2=new MyThread();
MyThread mt3=new MyThread();
mt1.start();//每个线程都各卖了10张,共卖了30张票
mt2.start();//但实际只有10张票,每个线程都卖自己的票
mt3.start();//没有达到资源共享
如果用Runnable就可以实现资源共享,下面看例子:
class MyThread implements Runnable{
private int ticket=10;
public void run(){
for(int i=0;i&20;i++){
if(this.ticket&0){
System.out.println("卖票:ticket"+this.ticket--);
public class RunnableTicket {
public static void main(String[] args) {
MyThread mt=new MyThread();
new Thread(mt).start();//同一个mt,但是在Thread中就不可以,如果用同一
new Thread(mt).start();//个实例化对象mt,就会出现异常
new Thread(mt).start();
虽然现在程序中有三个线程,但是一共卖了10张票,也就是说使用Runnable实现多线程可以达到资源共享目的。
Runnable接口和Thread之间的联系:
public class Thread extends Object implements Runnable
发现Thread类也是Runnable接口的子类。
class hello implements Runnable {
public void run() {
for (int i = 0; i & 3; i++) {
System.out.println(Thread.currentThread().getName());
public static void main(String[] args) {
hello he = new hello();
new Thread(he,"A").start();
new Thread(he,"B").start();
new Thread(he).start();
【运行结果】:
说明如果我们没有指定名字的话,系统自动提供名字。
判断线程是否启动
class hello implements Runnable {
public void run() {
for (int i = 0; i & 3; i++) {
System.out.println(Thread.currentThread().getName());
public static void main(String[] args) {
hello he = new hello();
Thread demo = new Thread(he);
System.out.println("线程启动之前---》" + demo.isAlive());
demo.start();
System.out.println("线程启动之后---》" + demo.isAlive());
【运行结果】
线程启动之前---》false
线程启动之后---》true
主线程也有可能在子线程结束之前结束。并且子线程不受影响,不会因为主线程的结束而结束。
* @author Rollen-Holt 线程的强制执行
class hello implements Runnable {
public void run() {
for (int i = 0; i & 3; i++) {
System.out.println(Thread.currentThread().getName());
public static void main(String[] args) {
hello he = new hello();
Thread demo = new Thread(he,"线程");
demo.start();
for(int i=0;i&50;++i){
demo.join();
//强制执行demo
}catch (Exception e) {
e.printStackTrace();
System.out.println("main 线程执行--&"+i);
【运行的结果】:
main 线程执行--&0
main 线程执行--&1
main 线程执行--&2
main 线程执行--&3
main 线程执行--&4
main 线程执行--&5
main 线程执行--&6
main 线程执行--&7
main 线程执行--&8
main 线程执行--&9
main 线程执行--&10
main 线程执行--&11
main 线程执行--&12
main 线程执行--&13
* @author Rollen-Holt 线程的休眠
class hello implements Runnable {
public void run() {
for (int i = 0; i & 3; i++) {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
System.out.println(Thread.currentThread().getName() + i);
public static void main(String[] args) {
hello he = new hello();
Thread demo = new Thread(he, "线程");
demo.start();
【运行结果】:(结果每隔2s输出一个)
* @author Rollen-Holt 线程的中断
class hello implements Runnable {
public void run() {
System.out.println("执行run方法");
Thread.sleep(10000);
System.out.println("线程完成休眠");
} catch (Exception e) {
System.out.println("休眠被打断");
//返回到程序的调用处
System.out.println("线程正常终止");
public static void main(String[] args) {
hello he = new hello();
Thread demo = new Thread(he, "线程");
demo.start();
Thread.sleep(2000);
}catch (Exception e) {
e.printStackTrace();
demo.interrupt(); //2s后中断线程
【运行结果】:
执行run方法
休眠被打断
在java程序中,只要前台有一个线程在运行,整个java程序进程不会消失,所以此时可以设置一个后台线程,这样即使java进程消失了,此后台线程依然能够继续运行。
* @author Rollen-Holt 后台线程
class hello implements Runnable {
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() + "在运行");
public static void main(String[] args) {
hello he = new hello();
Thread demo = new Thread(he, "线程");
demo.setDaemon(true);
demo.start();
虽然有一个死循环,但是程序还是可以执行完的。因为在死循环中的线程操作已经设置为后台运行了。
* @author Rollen-Holt 线程的优先级
class hello implements Runnable {
public void run() {
for(int i=0;i&5;++i){
System.out.println(Thread.currentThread().getName()+"运行"+i);
public static void main(String[] args) {
Thread h1=new Thread(new hello(),"A");
Thread h2=new Thread(new hello(),"B");
Thread h3=new Thread(new hello(),"C");
h1.setPriority(8);
h2.setPriority(2);
h3.setPriority(6);
h1.start();
h2.start();
h3.start();
【运行结果】:
但是不要误以为优先级越高就先执行。谁先执行还是取决于谁先去的CPU的资源。所以B运行了1次,C开始运行。运行完轮到B,另外,主线程的优先级是5。
线程的礼让。
在线程操作中,也可以使用yield()方法,将一个线程的操作暂时交给其他线程执行。
* @author Rollen-Holt 线程的优先级
class hello implements Runnable {
public void run() {
for(int i=0;i&5;++i){
System.out.println(Thread.currentThread().getName()+"运行"+i);
System.out.println("线程的礼让");
Thread.currentThread().yield();
public static void main(String[] args) {
Thread h1=new Thread(new hello(),"A");
Thread h2=new Thread(new hello(),"B");
h1.start();
h2.start();
线程的礼让
线程的礼让
同步和死锁:
【问题引出】:比如说对于买票系统,有下面的代码:
class hello implements Runnable {
public void run() {
for(int i=0;i&10;++i){
if(count&0){
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
System.out.println(count--);
public static void main(String[] args) {
hello he=new hello();
Thread h1=new Thread(he);
Thread h2=new Thread(he);
Thread h3=new Thread(he);
h1.start();
h2.start();
h3.start();
private int count=5;
【运行结果】:
这里出现了-1,显然这个是错的。,应该票数不能为负值。
如果想解决这种问题,就需要使用同步。所谓同步就是在统一时间段中只有有一个线程运行,
其他的线程必须等到这个线程结束之后才能继续执行。
【使用线程同步解决问题】
采用同步的话,可以使用同步代码块和同步方法两种来完成。
【同步代码块】:
语法格式:
synchronized(同步对象){
//需要同步的代码
但是一般都把当前对象this作为同步对象。
比如对于上面的买票的问题,如下:
class hello implements Runnable {
public void run() {
for(int i=0;i&10;++i){
synchronized (this) {
if(count&0){
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
System.out.println(count--);
public static void main(String[] args) {
hello he=new hello();
Thread h1=new Thread(he);
Thread h2=new Thread(he);
Thread h3=new Thread(he);
h1.start();
h2.start();
h3.start();
private int count=5;
【运行结果】:(每一秒输出一个结果)
【同步方法】
也可以采用同步方法。
语法格式为synchronized 方法返回类型方法名(参数列表){
// 其他代码
现在,我们采用同步方法解决上面的问题。
class hello implements Runnable {
public void run() {
for (int i = 0; i & 10; ++i) {
public synchronized void sale() {
if (count & 0) {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println(count--);
public static void main(String[] args) {
hello he = new hello();
Thread h1 = new Thread(he);
Thread h2 = new Thread(he);
Thread h3 = new Thread(he);
h1.start();
h2.start();
h3.start();
private int count = 5;
【运行结果】(每秒输出一个)
提醒一下,当多个线程共享一个资源的时候需要进行同步,但是过多的同步可能导致死锁。
此处列举经典的生产者和消费者问题。
【生产者和消费者问题】
先看一段有问题的代码。
class Info {
public String getName() {
public void setName(String name) {
this.name =
public int getAge() {
public void setAge(int age) {
this.age =
private String name = "Rollen";
private int age = 20;
class Producer implements Runnable{
private Info info=
Producer(Info info){
public void run(){
boolean flag=
for(int i=0;i&25;++i){
.setName("Rollen");
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
.setAge(20);
.setName("chunGe");
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
.setAge(100);
* 消费者类
class Consumer implements Runnable{
private Info info=
public Consumer(Info info){
public void run(){
for(int i=0;i&25;++i){
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
System.out..getName()+"&----&"+.getAge());
class hello{
public static void main(String[] args) {
Info info=new Info();
Producer pro=new Producer(info);
Consumer con=new Consumer(info);
new Thread(pro).start();
new Thread(con).start();
【运行结果】:
Rollen&----&100
chunGe&----&20
chunGe&----&100
Rollen&----&100
chunGe&----&20
Rollen&----&100
Rollen&----&100
Rollen&----&100
chunGe&----&20
chunGe&----&20
chunGe&----&20
Rollen&----&100
chunGe&----&20
Rollen&----&100
chunGe&----&20
Rollen&----&100
chunGe&----&20
Rollen&----&100
chunGe&----&20
Rollen&----&100
chunGe&----&20
Rollen&----&100
chunGe&----&20
Rollen&----&100
chunGe&----&20
大家可以从结果中看到,名字和年龄并没有对于。
那么如何解决呢?
1)加入同步
2)加入等待和唤醒
先来看看加入同步会是如何。
class Info {
public String getName() {
public void setName(String name) {
this.name =
public int getAge() {
public void setAge(int age) {
this.age =
public synchronized void set(String name, int age){
this.name=
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
public synchronized void get(){
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
System.out.println(this.getName()+"&===&"+this.getAge());
private String name = "Rollen";
private int age = 20;
class Producer implements Runnable {
private Info info =
Producer(Info info) {
public void run() {
boolean flag =
for (int i = 0; i & 25; ++i) {
if (flag) {
.set("Rollen", 20);
.set("ChunGe", 100);
* 消费者类
class Consumer implements Runnable {
private Info info =
public Consumer(Info info) {
public void run() {
for (int i = 0; i & 25; ++i) {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
class hello {
public static void main(String[] args) {
Info info = new Info();
Producer pro = new Producer(info);
Consumer con = new Consumer(info);
new Thread(pro).start();
new Thread(con).start();
【运行结果】:
Rollen&===&20
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
Rollen&===&20
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
ChunGe&===&100
从运行结果来看,错乱的问题解决了,现在是Rollen 对应20,ChunGe对于100
,但是还是出现了重复读取的问题,也肯定有重复覆盖的问题。如果想解决这个问题,就需要使用Object类帮忙了、
,我们可以使用其中的等待和唤醒操作。
要完成上面的功能,我们只需要修改Info类饥渴,在其中加上标志位,并且通过判断标志位完成等待和唤醒的操作,代码如下:
class Info {
public String getName() {
public void setName(String name) {
this.name =
public int getAge() {
public void setAge(int age) {
this.age =
public synchronized void set(String name, int age){
if(!flag){
super.wait();
}catch (Exception e) {
e.printStackTrace();
this.name=
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
super.notify();
public synchronized void get(){
super.wait();
}catch (Exception e) {
e.printStackTrace();
Thread.sleep(100);
}catch (Exception e) {
e.printStackTrace();
System.out.println(this.getName()+"&===&"+this.getAge());
super.notify();
private String name = "Rollen";
private int age = 20;
private boolean flag=
class Producer implements Runnable {
private Info info =
Producer(Info info) {
public void run() {
boolean flag =
for (int i = 0; i & 25; ++i) {
if (flag) {
.set("Rollen", 20);
.set("ChunGe", 100);
* 消费者类
class Consumer implements Runnable {
private Info info =
public Consumer(Info info) {
public void run() {
for (int i = 0; i & 25; ++i) {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
class hello {
public static void main(String[] args) {
Info info = new Info();
Producer pro = new Producer(info);
Consumer con = new Consumer(info);
new Thread(pro).start();
new Thread(con).start();
【程序运行结果】:
Rollen&===&20
ChunGe&===&100
Rollen&===&20
ChunGe&===&100
Rollen&===&20
ChunGe&===&100
Rollen&===&20
ChunGe&===&100
Rollen&===&20
ChunGe&===&100
Rollen&===&20
ChunGe&===&100
Rollen&===&20
ChunGe&===&100
Rollen&===&20
ChunGe&===&100
Rollen&===&20
ChunGe&===&100
Rollen&===&20
ChunGe&===&100
Rollen&===&20
ChunGe&===&100
Rollen&===&20
ChunGe&===&100
Rollen&===&20
现在看结果就可以知道,之前的问题完全解决。
浏览: 4176 次Java中Runnable和Thread的区别的疑问
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;Thread类是在java.lang包中定义的。一个类只要继承了Thread类同时覆写了本类中的run()
方法就可以实现多线程操作了,但是一个类只能继承一个父类,这是此方法的局限。
在中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下好处:
1、避免点继承的局限,一个类可以继承多个接口。
2、适合于资源的共享
以上为在其他博客上看到的观点,还有一篇专门文章讲&Runnable可以实现资源共享但Thread不能实现资源共享的原因&,这是链接,但是如果换另一种思路看起来也是可以实现Thread资源共享的,不知对不对&
一个继承自Thread类:
package com.zz.
* 扩展自Thread类
* Copyright 日
* created by txxs
* all right reserved
public class ThreadDemo0 extends Thread {
private int ticket = 5;
public void run(){
for(int i =0;i&500;i++){
if(this.ticket&0){
System.out.println(Thread.currentThread().getName()+&卖票----&&+(this.ticket--));
一个实现Runnable接口
package com.zz.
* 实现Runnable接口
* Copyright 日
* created by txxs
* all right reserved
public class ThreadDemo1 implements Runnable {
private int ticket =5;
public void run(){
for(int i =0;i&500;i++){
if(this.ticket&0){
System.out.println(Thread.currentThread().getName()+&卖票----&&+(this.ticket--));
分别对应的测试类和实现的结果:
ThreadDemo0的测试类:
package com.zz.
* 测试继承自Thread类
* Copyright 日
* created by txxs
* all right reserved
public class ThreadTest2 {
public static void main(String[] args) {
* 之前的博客(https://blog.chinaunix.net/uid--id-310538.html)说,
* 继承Thread类的实例,用同一个实例化对象就会异常,不明白,亲自试了一下
* 发现这两种方式都可以实现线程共享,不明白为什么大家都说不可以
ThreadDemo0 ticketThread0 = new ThreadDemo0();
Thread th4 = new Thread(ticketThread0);
th4.setName(&售票口10&);
Thread th5 = new Thread(ticketThread0);
th5.setName(&售票口11&);
Thread th6 = new Thread(ticketThread0);
th6.setName(&售票口12&);
th4.start();
th5.start();
th6.start();
ThreadDemo0结果:
ThreadDemo1的测试类:
package com.zz.
* 实现Runnable接口
* Copyright 日
* created by txxs
* all right reserved
public class ThreadTest1 {
public static void main(String[] args) {
ThreadDemo1 ticketThread1 = new ThreadDemo1();
Thread th1 = new Thread(ticketThread1);
th1.setName(&售票口7&);
Thread th2 = new Thread(ticketThread1);
th2.setName(&售票口8&);
Thread th3 = new Thread(ticketThread1);
th3.setName(&售票口9&);
th1.start();
th2.start();
th3.start();
运行结果:
从以上的运行结果可以看出,继承Thread和实现Runnable都实现了资源共享,但是为什么大家都认为这种方式不可以呢,还是我实现的方式有问题?5359人阅读
java进阶(11)
在我们开发的过程中常常会碰到多线程的问题,对于多线程的实现方式主要有两种:实现Runnable接口、继承Thread类。对于这两种多线程的实现方式也是有着一些差异。既然实现了多线程那必然离不开管理这些线程,当问题比简单时一个或者几个线程就OK了,也涉及不到效率问题。一旦线程数量多起来的时候,必然躲不过这些线程的创建与销毁,而往往这是很浪费时间的。这时就需要利用线程池来进行管理,既免去了我们创建线程和销毁线程的代码,也提高了程序的效率。下面针对以上问题做出相关讲解。
一、Runnable、Thread比较
首先阐述实现Runnable的好处:
java不允许多继承,因此实现了Runnable接口的类可以再继承其他类。
方便资源共享,即可以共享一个对象实例???(从很多博客中看到这样描述,但是此处有疑问,例子如下)
下面来通过具体代码来解释上述优点,网上很流行的买票系统,假设有10张票,首先通Thread来进行购买。代码如下:
public class TicketThread extends Thread{
private int ticket = 10;
public void run(){
for(int i =0;i&10;i++){
synchronized (this){
if(this.ticket&0){
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"卖票----&"+(this.ticket--));
} catch (InterruptedException e) {
e.printStackTrace();
public static void main(String[] arg){
TicketThread t1 = new TicketThread();
new Thread(t1,"线程1").start();
new Thread(t1,"线程2").start();
线程1卖票—-&10
线程1卖票—-&9
线程1卖票—-&8
线程2卖票—-&7
线程2卖票—-&6
线程1卖票—-&5
线程1卖票—-&4
线程2卖票—-&3
线程2卖票—-&2
线程1卖票—-&1
实现Runnable接口:
package threadT
public class TicketRunnable implements Runnable{
private int ticket = 10;
public void run() {
for(int i =0;i&10;i++){
synchronized (this){
if(this.ticket&0){
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"卖票----&"+(this.ticket--));
} catch (Exception e) {
e.printStackTrace();
public static void main(String[] arg){
TicketRunnable t1 = new TicketRunnable();
new Thread(t1, "线程1").start();
new Thread(t1, "线程2").start();
线程1卖票—-&10
线程1卖票—-&9
线程1卖票—-&8
线程1卖票—-&7
线程2卖票—-&6
线程2卖票—-&5
线程2卖票—-&4
线程2卖票—-&3
线程2卖票—-&2
线程2卖票—-&1
从这两个例子可以看出,Thread也可以资源共享啊,为什么呢,因为Thread本来就是实现了Runnable,包含Runnable的功能是很正常的啊!!至于两者的真正区别最主要的就是一个是继承,一个是实现;其他还有一些面向对象的思想,Runnable就相当于一个作业,而Thread才是真正的处理线程,我们需要的只是定义这个作业,然后将作业交给线程去处理,这样就达到了松耦合,也符合面向对象里面组合的使用,另外也节省了函数开销,继承Thread的同时,不仅拥有了作业的方法run(),还继承了其他所有的方法。综合来看,用Runnable比Thread好的多。
针对本例再补充一点,在以上程序中,如果去掉同步代码块,则会出现其中一人购买第0张票的情况,所以我们在做多线程并行的时候一定要时刻考虑到边界值的问题,在关键代码处必须要做好同步处理。
二、线程池
创建线程池主要有三个静态方法供我们使用,由Executors来进行创建相应的线程池:
public static ExecutorSevice newSingleThreadExecutor()
public static ExecutorSevice newFixedThreadPool(int nThreads)
public static ExecutorSevice newCachedThreadPool()
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
newSingleThreadExecutor返回以个包含单线程的Executor,将多个任务交给此Exector时,这个线程处理完一个任务后接着处理下一个任务,若该线程出现异常,将会有一个新的线程来替代。
newFixedThreadPool返回一个包含指定数目线程的线程池,如果任务数量多于线程数量,那么没有执行的任务必须等待,直到有任务完成为止。
newCachedThreadPool根据用户的任务数创建相应的线程来处理,该线程池不会对线程数目加以限制,完全依赖于JVM能创建线程的数量,可能引起内存不足。
newScheduledThreadPool创建一个至少有n个线程空间大小的线程池。此线程池支持定时以及周期性执行任务的需求。
我们只需要把实现了Runnable的类的对象实例放入线程池,那么线程池就自动维护线程的启动、运行、销毁。我们不需要自行调用start()方法来开启这个线程。线程放入线程池之后会处于等待状态直到有足够空间时会唤醒这个线程。
private ExecutorService threadPool = Executors.newFixedThreadPool(5);
threadPool.execute(socketThread);
private ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(5);
threadPool.scheduleAtFixedRate(socketThread, 1000, 1000, TimeUnit.MILLISECONDS);
threadPool.scheduleWithFixedDelay(socketThread, 1000, 1000, TimeUnit.MILLISECONDS);
threadPool.shutdown();
threadPool.shutdownNow();
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:59566次
积分:1099
积分:1099
排名:千里之外
原创:58篇
评论:10条
(12)(2)(6)(4)(1)(2)(6)(1)(6)(9)(4)(3)(2)(9)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'

我要回帖

更多关于 thread runnable 的文章

 

随机推荐