Java 多线程实现方式主要有四种: 继承 Thread 类, 实现 Runnable 接口, 实现 Callable 接口通过 FutureTask 包装器来创建 Thread 线程, 使用 ExecutorService,Callable,Future 实现有返回结果的多线程.
其中前两种方式线程执行完后都没有返回值, 后两种是带返回值的.
方式一: 继承 Thread 类
重写 run() 方法, 调用 start() 方法执行.
需要注意的是: 为什么多线程的启动不是调用 run() 方法, 而是调用 start() 方法?
在 Java 开发中有一门 JNI(Java Native Interface) 技术, 这门技术的特点, 使用 Java 调用本机操作系统的函数, 但是这个技术不能离开特定的操作系统.
如果线程想要执行, 需要操作系统分配资源. 所以此操作严格来讲需要 JVM 根据不同的操作系统来实现的.
start() 方法中, 使用了 native 关键字修饰了方法, 而 native 关键字时根据不同的操作系统分配不同的资源.
start() 方法, 不仅仅要启动多线程执行的代码, 还需要根据不同的操作系统来分配资源
- package test;
- public class MyThread {
- public static void main(String[] args) {
- Test t1 = new Test("one");
- Test t2 = new Test("two");
- Test t3 = new Test("three");
- /**
- * 调用 Thread 类中的 start 方法, 才能进行多线程的操作, 而不是 run 方法
- * start() 方法不仅仅启动多线程代码的执行, 还需要根据不同的操作系统分配资源
- */
- try {// 调用 Thread 类中的 sleep 方法, 让线程等待指定的一段时间
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- t1.start();
- t2.start();
- t3.start();
- }
- }
- /**
- * 继承线程类 Thread, 重写 run() 方法, 在 run 方法中实现需要进行的数据操作
- * @author Administrator
- *
- */
- class Test extends Thread{
- private String name;
- public Test(String name) {
- this.name=name;
- }
- @Override
- public void run() {// 需要进行多进程的操作
- for (int i = 0; i <100; i++) {
- System.out.println(name+"===>"+i);
- }
- }
- }
方式二: 实现 Runnable 接口
实现 run 方法, 将 Runnable 对象作为参数放入到 Thread 构造方法中, 在调用 start() 方法.
- package test;
- /**
- * 测试 Runnable 接口
- * @author Administrator
- *
- */
- public class MyRunnable {
- public static void main(String[] args) {
- Demo mr1 = new Demo("A");
- Demo mr2 = new Demo("B");
- Demo mr3 = new Demo("C");
- // 将该对象作为参数, 传入到 Thread 类中, 在调用 start() 方法.
- new Thread(mr1).start();
- new Thread(mr2).start();
- new Thread(mr3).start();
- }
- }
- /**
- * 实现 Runnable 接口, 实现多线程
- * @author Administrator
- *
- */
- class Demo implements Runnable {
- private String name;
- public Demo(String name) {
- this.name = name;
- }
- @Override
- public void run() {
- for (int i = 0; i <300; i++) {
- System.out.println(name + "==>" + i);
- }
- }
- }
问题一: Thread 与 Runnable 有什么不同?
1,Thread 实现了 Runnable 接口, 使用 Runnable 接口可以避免单根继承的问题.
2,Runnable 接口实现的多线程可以比 Thread 类实现的多线程更加清楚的描述数据共享的概念.
问题二: 写出两种多线程实现操作?
- package test;
- /**
- * Runnable 接口比 Thread 类更加清楚的描述了数据共享的概念
- * @author Administrator
- *
- */
- public class ThreadAndRunnable {
- public static void main(String [] args){
- TestDemo1 t = new TestDemo1();
- new Thread(t).start();
- new Thread(t).start();
- new Thread(t).start();
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- System.out.println("======================================= 我是分割线 =======================================");
- /**
- * 这里虽然也可以数据共享,
- * 但是, TestDemo2 已经继承了 Thread 类, 而这里又要 new 三个 Thread 类出来,
- * 区调用 start 方法, 显得多此一举
- */
- TestDemo2 d1 = new TestDemo2();
- new Thread(d1).start();
- new Thread(d1).start();
- new Thread(d1).start();
- }
- }
- /**
- * 实现了 Runnable 接口的类, 可以明显的表示出数据共享的概念
- * @author Administrator
- *
- */
- class TestDemo1 implements Runnable{
- /**
- * 买票
- */
- private int numb = 20;
- @Override
- public void run() {
- for (int i = 0; i <200; i++) {
- if (this.numb> 0) {
- System.out.println("买票; numb ="+this.numb--);
- }
- }
- }
- }
- /**
- * Thread 类实现数据共享
- * @author Administrator
- *
- */
- class TestDemo2 extends Thread{
- private int num = 20;
- @Override
- public void run() {
- for (int i = 0; i <200; i++) {
- if(this.num> 0)
- System.out.println("买票; num ="+this.num--);
- }
- }
- }
方式三: 实现 Callable 接口通过 FutureTask 包装器来创建 Thread 线程
待续...
方式四: 使用 ExecutorService,Callable,Future 实现有返回结果的线程
待续...
来源: http://www.bubuko.com/infodetail-3128644.html