Java多线程2:实现多线程的两种方式
原文:http://www.cnblogs.com/skywang12345/p/3479063.html
常见的实现多线程的方式有2种,一是继承Thread类,二是实现 Runnable接口,还可以通过java.util.concurrent包中的线程池来实现多线程。
Thread和Runnable简介
Runnable是一个接口,该接口中只包含了一个run()方法。它的定义如下:
- public interface Runnable {
- public abstract void run();
- }
可以定义一个类A实现Runnable接口并重写run方法,然后通过new Thread(new A())的方式创建一个线程。
Thread是一个类。Thread本身就实现了Runnable接口。它的声明如下:
- public class Thread implements Runnable {
- }
Thread和Runnable的不同之处在于
Thread是类,而Runnable是接口;Thread本身是实现了Runnable接口的类。由于一个类只能有一个父类,但是却能实现多个接口,因此实现Runnable接口的方式相比于继承Thread类创建线程的方式具有更好的扩展性。
此外,Runnable还可以用于实现"资源的共享"。即多个线程都基于同一个Runnable对象建立的,它们会共享Runnable对象上的资源。
因此通常通过实现runnable接口实现多线程。
Thread和Runnable的多线程示例
1. 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(this.getName()+" 卖票:ticket"+this.ticket--);
- }
- }
- }
- }
- public class ThreadTest {
- public static void main(String[] args) {
- // 启动3个线程t1,t2,t3;每个线程各卖10张票!
- MyThread t1=new MyThread();
- MyThread t2=new MyThread();
- MyThread t3=new MyThread();
- t1.start();
- t2.start();
- t3.start();
- }
- }
运行结果
- Thread-0 卖票:ticket10
- Thread-1 卖票:ticket10
- Thread-2 卖票:ticket10
- Thread-1 卖票:ticket9
- Thread-0 卖票:ticket9
- Thread-1 卖票:ticket8
- Thread-2 卖票:ticket9
- Thread-1 卖票:ticket7
- Thread-0 卖票:ticket8
- Thread-1 卖票:ticket6
- Thread-2 卖票:ticket8
- Thread-1 卖票:ticket5
- Thread-0 卖票:ticket7
- Thread-1 卖票:ticket4
- Thread-2 卖票:ticket7
- Thread-1 卖票:ticket3
- Thread-0 卖票:ticket6
- Thread-1 卖票:ticket2
- Thread-2 卖票:ticket6
- Thread-2 卖票:ticket5
- Thread-2 卖票:ticket4
- Thread-1 卖票:ticket1
- Thread-0 卖票:ticket5
- Thread-2 卖票:ticket3
- Thread-0 卖票:ticket4
- Thread-2 卖票:ticket2
- Thread-0 卖票:ticket3
- Thread-2 卖票:ticket1
- Thread-0 卖票:ticket2
- Thread-0 卖票:ticket1
结果说明:
(01) MyThread继承于Thread,它是自定义个线程。每个MyThread都会卖出10张票。
(02) 主线程main创建并启动3个MyThread子线程。每个子线程都各自卖出了10张票。
2. 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(Thread.currentThread().getName()+" 卖票:ticket"+this.ticket--);
- }
- }
- }
- }
- public class RunnableTest {
- public static void main(String[] args) {
- MyThread mt=new MyThread();
- // 启动3个线程t1,t2,t3(它们共用一个Runnable对象),这3个线程一共卖10张票!
- Thread t1=new Thread(mt);
- Thread t2=new Thread(mt);
- Thread t3=new Thread(mt);
- t1.start();
- t2.start();
- t3.start();
- }
- }
运行结果
- Thread-0 卖票:ticket10
- Thread-2 卖票:ticket8
- Thread-1 卖票:ticket9
- Thread-2 卖票:ticket6
- Thread-0 卖票:ticket7
- Thread-2 卖票:ticket4
- Thread-1 卖票:ticket5
- Thread-2 卖票:ticket2
- Thread-0 卖票:ticket3
- Thread-1 卖票:ticket1
结果说明:
(01) 和上面"MyThread继承于Thread"不同;这里的MyThread实现了Thread接口。
(02) 主线程main创建并启动3个子线程,而且这3个子线程都是基于"mt这个Runnable对象"而创建的。运行结果是这3个子线程一共卖出了10张票。这说明它们是共享了MyThread接口的。
实际上这个程序卖出的票有很能不止十张,问题出在多线程对ticket这个竞争资源的互斥访问上,下面是一种解决方法。
- class MyThread implements Runnable{
- private volatile int ticket=10;
- public synchronized void run(){
- for(int i=0;i<20;i++){
- if(this.ticket>0){
- System.out.println(Thread.currentThread().getName()+" 卖票:ticket"+this.ticket--);
- }
- }
- }
- }
Java多线程2:实现多线程的两种方式的更多相关文章
- 1.java多线程_实现线程的两种方式
1.java多线程基本知识 1.1.进程介绍 不管是我们开发的应用程序,还是我们运行的其他的应用程序,都需要先把程序安装在本地的硬盘上.然后找到这个程序的启动文件, 启动程序的时候,其实是电脑把当前的 ...
- 遍历Map集合:java.util.Map.Entry、KeySet两种方式
遍历Map集合的两种方式: 1.用KeySet Map.keySet(),返回一个存放所有key的set集合,通过遍历集合,根据key值取出所有的value值. Map<String,Strin ...
- Java并发--线程间协作的两种方式:wait、notify、notifyAll和Condition
在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界 ...
- java文件末尾追加内容的两种方式
java 开发中,偶尔会遇到在文件末尾对文件内容进行追加,实际上有多种方式可以实现,简单介绍两种: 一种是通过RandomAccessFile类实现,另一种是通过FileWriter类来实现. 实现方 ...
- Java中 单例(Singleton)的两种方式
第一种(饿汉式单例模式):在声明变量时实例化 public class Singleton { //静态初始化自动实例化 private static Singleton instance = new ...
- Java字符流读写数据的两种方式
第一种方式:逐个字符进行读写操作(代码注释以及详细内容空闲补充) package IODemo; import java.io.FileReader; import java.io.FileWrite ...
- java发送http get请求的两种方式
长话短说,废话不说 一.第一种方式,通过HttpClient方式,代码如下: public static String httpGet(String url, String charset) thro ...
- Java代码模拟http请求的两种方式
z这里用百度地图的逆地理编码接口为例, 第一种方式:(通过jdk中的java.net包) 引入工具类 import java.net.URL; import java.net.URLConnectio ...
- JAVA·多线程:创建线程的两种方式
1.–扩展java.lang.Thread类 package multiThread; public class Thread02extThread { public static void main ...
- java制作二维码的两种方式
原博:http://www.importnew.com/15028.html Zebra Crossing(ZXing)是一个很棒的,几乎可以在所有平台(Android.JavaSE.iPhone.R ...
随机推荐
- 动画气泡指示当前滑动值--第三方开源--DiscreteSeekbar
DiscreteSeekbar在github上的项目主页是:https://github.com/AnderWeb/discreteSeekBar DiscreteSeekbar可以自定制的属性很多, ...
- 移植Oracle procedure 到 postgresql
1.登录postgresql psql -h 192.168.137.131 -p 5432 postgres satusc@6789#JKL 2.创建用户 CREATE USER name thun ...
- 1066. Root of AVL Tree (25)
An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child sub ...
- C语言文件函数
FILE *fp: 其中的FILE应该大写,它实际上是系统定义的一个结构,在stdio.h文件中.该结构中有文件名,文件状态,文件当前的读写信息等. fp是指向FILE结构的指针变量,通过fp可以找到 ...
- Hadoop管理员的十个最佳实践(转)
前言 接触Hadoop有两年的时间了,期间遇到很多的问题,既有经典的NameNode和JobTracker内存溢出故障,也有HDFS存储小文件问题,既有任务调度问题,也有MapReduce性能问题.遇 ...
- nodejs fs 模块的用途
/*** New node filefs 操作*/var fs = require(“fs”); /*创建文件 var fileName = “anps_hsj”;fs.mkdir(fileName, ...
- define的用法
define的用法小结 define的用法只是一种纯粹的替换功能,宏定义的替换是预处理器处理的替换. 一:简单的宏定义用法 格式:#define 标识符 替换内容 替换的内容可以是数字,字符,字符串, ...
- Aspose 数字和日期 设置
Microsoft Excel一个非常强大的功能就是使客户可以设置数字和日期的显示格式,众所周知数字可以显示为不同的值格式,包含:小数.货币.百分数.分数.账面价值等,同样地Aspose.Cells也 ...
- 3240: [Noi2013]矩阵游戏
Description 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储).她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的 ...
- POJ 3553 Task schedule
原题链接:http://poj.org/problem?id=3553 这道题主要就是贪心思想吧,对于每个job,根据其截止时间 dj 从小到大排序,我们必须要尽快把dj最小的job完成掉,这样才能使 ...