Java基础之多线程(二)

Java多线程实现方式主要有四种:继承Thread类、实现Runnable接口、实现Callable接口经过FutureTask包装器来建立Thread线程、使用ExecutorService、Callable、Future实现有返回结果的多线程。html

其中前两种方式线程执行完后都没有返回值,后两种是带返回值的。 java

使用Thread对象的interrupt()方法,打断线程睡眠则会抛出interrupted异常git

System.in.read();读取键盘输入多线程

方式一:继承Thread类(线程没有返回值,在java.lang包中less

  重写run()方法,调用start()方法执行。ide

  须要注意的是:为何多线程的启动不是调用run()方法,而是调用start()方法?函数

      在Java开发中有一门JNI(Java Native Interface)技术,这门技术的特色,使用Java调用本机操做系统的函数,可是这个技术不能离开特定的操做系统。测试

若是线程想要执行,须要操做系统分配资源。因此此操做严格来说须要JVM根据不一样的操做系统来实现的。this

  start()方法中,使用了native关键字修饰了方法,而native关键字时根据不一样的操做系统分配不一样的资源。url

  start()方法,不单单要启动多线程执行的代码,还须要根据不一样的操做系统来分配资源

1 package test; 2 3 public class MyThread { 4 public static void main(String[] args) { 5 Test t1 = new Test("one"); 6 Test t2 = new Test("two"); 7 Test t3 = new Test("three"); 8 /** 9 * 调用Thread类中的start方法,才能进行多线程的操做,而不是run方法 10 * start()方法不单单启动多线程代码的执行,还须要根据不一样的操做系统分配资源 11 */ 12 try {//调用Thread类中的sleep方法,让线程等待指定的一段时间 13 Thread.sleep(1000); 14 } catch (InterruptedException e) { 15  e.printStackTrace(); 16  } 17  t1.start(); 18  t2.start(); 19  t3.start(); 20  } 21 } 22 23 /** 24 * 继承线程类Thread,重写run()方法,在run方法中实现须要进行的数据操做 25 * @author Administrator 26 * 27 */ 28 class Test extends Thread{ 29 30 private String name; 31 32 public Test(String name) { 33 this.name=name; 34  } 35  @Override 36 public void run() {//须要进行多进程的操做 37 for (int i = 0; i < 100; i++) { 38 System.out.println(name+"===>"+i); 39  } 40  } 41 }

 方式二:实现Runnable接口(线程没有返回值,在java.lang包中)

  该接口标注为:@Java.lang.FactionInterface

    实现run方法,将Runnable对象做为参数放入到Thread构造方法中,在调用start()方法。

1 package test; 2 /** 3 * 测试Runnable接口 4 * @author Administrator 5 * 6 */ 7 public class MyRunnable { 8 public static void main(String[] args) { 9 Demo mr1 = new Demo("A"); 10 Demo mr2 = new Demo("B"); 11 Demo mr3 = new Demo("C"); 12 //将该对象做为参数,传入到Thread类中,在调用start()方法。 13 new Thread(mr1).start(); 14 new Thread(mr2).start(); 15 new Thread(mr3).start(); 16  } 17 } 18 19 /** 20 * 实现Runnable接口,实现多线程 21 * @author Administrator 22 * 23 */ 24 class Demo implements Runnable { 25 26 private String name; 27 28 public Demo(String name) { 29 this.name = name; 30  } 31 32  @Override 33 public void run() { 34 for (int i = 0; i < 300; i++) { 35 System.out.println(name + "==>" + i); 36  } 37  } 38 39 }

问题一:Thread与Runnable有什么不一样?

  一、Thread实现了Runnable接口,使用Runnable接口能够避免单根继承的问题。

  二、Runnable接口实现的多线程能够比Thread类实现的多线程更加清楚的描述数据共享的概念。

问题二:写出两种多线程实现操做?

1 package test; 2 /** 3 * Runnable接口比Thread类更加清楚的描述了数据共享的概念 4 * @author Administrator 5 * 6 */ 7 public class ThreadAndRunnable { 8 9 public static void main(String [] args){ 10 TestDemo1 t = new TestDemo1(); 11 new Thread(t).start(); 12 new Thread(t).start(); 13 new Thread(t).start(); 14 try { 15 Thread.sleep(2000); 16 } catch (InterruptedException e) { 17 // TODO Auto-generated catch block 18  e.printStackTrace(); 19  } 20 System.out.println("=======================================我是分割线======================================="); 21 /** 22 * 这里虽然也能够数据共享, 23 * 可是,TestDemo2已经继承了Thread类,而这里又要new三个Thread类出来, 24 * 区调用start方法,显得画蛇添足 25 */ 26 TestDemo2 d1 = new TestDemo2(); 27 new Thread(d1).start(); 28 new Thread(d1).start(); 29 new Thread(d1).start(); 30  } 31 32 } 33 34 /** 35 * 实现了Runnable接口的类,能够明显的表示出数据共享的概念 36 * @author Administrator 37 * 38 */ 39 class TestDemo1 implements Runnable{ 40 /** 41 * 买票 42 */ 43 private int numb = 20; 44 45  @Override 46 public void run() { 47 for (int i = 0; i < 200; i++) { 48 if (this.numb > 0) { 49 System.out.println("买票;numb = "+this.numb--); 50  } 51  } 52  } 53 } 54 55 /** 56 * Thread类实现数据共享 57 * @author Administrator 58 * 59 */ 60 class TestDemo2 extends Thread{ 61 private int num = 20; 62  @Override 63 public void run() { 64 for (int i = 0; i < 200; i++) { 65 if(this.num > 0) 66 System.out.println("买票;num = "+this.num--); 67  } 68  } 69 70 }

 

方式三:实现Callable接口经过FutureTask包装器来建立Thread线程(线程有返回值,该接口在java.util.concurrent包中)

1 @java.lang.FactionalInterface 2 public interface Callable<V>{ 3 public V call() throws Exception; 4 }

从JDK1.5开始提供一个类java.util.concurrentFutureTask<V>,这个类主要负责Callable接口对象操做的,该类的定义结构为:

1 public class FutureTask<V> extends Object implements RunnableFuture<V>
 2 
 3 //然而RunnableFuture有是什么?
 4 public interface RunnableFuture<V> extends Runnable,Future<V>
 5 
 6 //然而FutureTask<V>接口的构造方法内,接受了Callable接口对象
 7 public FutureTask(Callable<V> callable) 8 //接受callable对象的目的:取得call()方法的结果,只有经过FutureTask类才能获得返回的 //结果
1 package test; 2 3 import java.util.concurrent.Callable; 4 import java.util.concurrent.FutureTask; 5 /** 6 * Callable接口实现多线程实例,能够获得返回的数据 7 * @author Administrator 8 * 9 */ 10 public class MyCllable { 11 12 public static void main(String[] args) throws Exception{ 13 TestDemo t1 = new TestDemo(); 14 TestDemo t2 = new TestDemo(); 15 FutureTask<String> task1 =new FutureTask<String>(t1); 16 FutureTask<String> task2 =new FutureTask<String>(t2); 17 /** 18 * FutureTask类是Runnable接口子类,因此能够做为构造参数调用start()方法 19 */ 20 new Thread(task1).start();//启动多线程 21 new Thread(task2).start();//启动多线程 22 System.out.println("task1===>"+task1.get());//获得返回的结果 23 System.out.println("task2===>"+task2.get());//获得返回的结果 24  } 25 26 } 27 28 class TestDemo implements Callable<String>{ 29 30 private int num = 20; 31 32  @Override 33 public String call() throws Exception { 34 for (int i = 0; i < 200; i++) { 35 if(this.num > 0){ 36 System.out.println("使用Callable接口实现多线程:"+num--); 37  } 38  } 39 return "数据归零"; 40  } 41 42 }

示例:写一个线程类输出001—999启动10条线程同时执行该类,每一个线程要都有机会,并且不能重复而其有序

 1 package com.zelin.lesson.test;  2 
 3 import java.text.NumberFormat;  4 
 5 /**
 6  * 编写一个线程类,启动10条线程同时执行该类,要求输出效果以下所示  7  *    001  8  * 002  9  * 003 10  * …. 11  * 999 12  * 输出001—999 每一个线程要都有机会,并且不能重复而其有序 13  */
14 public class TestThread { 15     public static void main(String[] args) { 16         Thread0 t = new Thread0(); 17         for (int i = 0; i < 10; i++) { 18             new Thread(t).start(); 19  } 20  } 21 } 22 
23 class Thread0 implements Runnable{ 24     //1.定义变量
25     private int tickets = 1; 26  @Override 27     public void run() { 28         while(true){ 29             synchronized (this){ 30                 if(tickets == 1000)  break; 31                 //2.将变量进行格式化处理
32                 NumberFormat numberFormat = NumberFormat.getInstance(); 33                 //3.设置输出的数字的最小整数位数
34                 numberFormat.setMinimumIntegerDigits(3); 35                 //4.对数字进行格式化处理
36                 String format = numberFormat.format(tickets++); 37                 //5.输出
38  System.out.println(format); 39  } 40  } 41  } 42 }

     线程(三)点我

相关文章
相关标签/搜索