多线程

2018-07-17 03:58:19来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

多线程

实现多线程共有两种方法:①继承一个Thread类;②实现Runnable、Callable接口(推荐)

一、继承Thread类实现多线程

Thread是一个线程操作的核心类,定义一个线程的主类最简单的方法就是继承Thread类,而后覆写类中的run()方法。实现如下(首先定义一个主体类,而后启动多线程即为调用Thread中的start()方法):

 

 1 class MyThread extends java.lang.Thread{//线程主体类
 2     private String title;
 3     public MyThread(String title){ 
 4         this.title = title; 
 5     }
 6     @Override
 7     public void run() {//所有的线程从此处执行
 8         for (int x = 0; x<10; x++){
 9             System.out.println(this.title + ",x = " + x); 
10         } 
11     }
12 }
13 public class Thread {
14     public static void main(String[] args) {
15         //创建线程
16         MyThread mt1 =new MyThread("A");
17         MyThread mt2 =new MyThread("B");
18         MyThread mt3 =new MyThread("C");
19         //启动多线程
20         mt1.start();
21         mt2.start();
22         mt3.start();
23     }
24 }

 

执行结果:多个线程交替执行

二、Runnable接口实现多线程

Thread类继承的缺点是单继承局限,而Runnable则没有这个缺点,其定义如下(使用的仍是Thread类的start()方法):

class MyRunnable implements Runnable {
    private String title;// 共10张票

    public MyRunnable(String title) {
        this.title = title;
    }
    @Override
    public void run() {//所有的线程从此处执行
        for (int x= 0; x<10; x++) {
            System.out.println(this.title + ",x = " + x);
        }

    }
}
public class TestRunnable {
    public static void main(String[] args) { 
        //创建线程
        MyThread mt1 =new MyThread("A");
        MyThread mt2 =new MyThread("B");
        MyThread mt3 =new MyThread("C");
        //启动多线程
        new java.lang.Thread(mt1).start();
        new java.lang.Thread(mt2).start();
        new java.lang.Thread(mt3).start();
    }
}

 

或者使用匿名内部类来定义:

 1 class MyRunnable implements Runnable {
 2     private String title;// 共10张票
 3 
 4     public MyRunnable(String title) {
 5         this.title = title;
 6     }
 7     @Override
 8     public void run() {//所有的线程从此处执行
 9         for (int x= 0; x<10; x++) {
10             System.out.println(this.title + ",x = " + x);
11         }
12 
13     }
14 }
15 public class TestRunnable {
16     public static void main(String[] args) {
17         new java.lang.Thread(new Runnable() {
18             @Override
19             public void run() {
20                 System.out.println("Hello");
21             }
22         }).start();
23     }
24 }

 

Runnable接口可以比Thread有更好的实现数据共享的概念,即产生若干线程进行同一数据的处理操作。实现如下:

 1 class MyRunnable implements Runnable {
 2     private int ticket = 10;// 共10张票
 3     @Override
 4     public void run() {//所有的线程从此处执行
 5         for (int x= 0; x<20; x++) {
 6             if (this.ticket > 0)
 7                 System.out.println("卖票,ticket:" + ",x = " + this.ticket--);
 8         }
 9 
10     }
11 }
12 public class TestRunnable {
13     public static void main(String[] args) {
14         MyRunnable mt = new MyRunnable();
15         new java.lang.Thread(mt).start();
16         new java.lang.Thread(mt).start();
17         new java.lang.Thread(mt).start();
18     }
19 }

 

执行结果:(三个线程之间的数据实现了共享)

卖票,ticket:,x = 10
卖票,ticket:,x = 8
卖票,ticket:,x = 9
卖票,ticket:,x = 6
卖票,ticket:,x = 7
卖票,ticket:,x = 4
卖票,ticket:,x = 5
卖票,ticket:,x = 1
卖票,ticket:,x = 2
卖票,ticket:,x = 3

 

三、Collable实现多线程

由于Runnable方法中的多线程没有返回值,难以满足某些需要一些返回值的程序,因此使用Collable来实现多线程。实现过程如下:(①定义Collable线程主体类②使用Thread中start方法启动多线程)

 1 import java.util.concurrent.Callable;
 2 import java.util.concurrent.FutureTask;
 3 
 4 class MyCallable implements Callable<String>{//线程主体类
 5     public String call() throws Exception{
 6         for (int x = 20; x > 0; x--)
 7             System.out.println("卖票:" + x);
 8         return "票卖完了……";
 9     }
10 }
11 public class TestCallable {
12     public static void main(String[] args) throws Exception{
13         FutureTask<String> task = new FutureTask<String>(new MyCallable());
14         new java.lang.Thread(task).start();//启动多线程
15         System.out.println(task.get());
16 
17     }
18 }

 

四、多线程的命名和取得

Thread类提供的线程名称的操作方法:

NO.

方法

类型

描述

1

Public Thread(Runnable target,String name)

构造

创建线程时设置好名字

2

Public final void setName(String name)

普通

设置线程名字

3

Public final String getName()

普通

取得线程名字

      取得当前正在执行的线程的对象:public static Thread currentThread()

取得线程姓名执行如下:

 1 class MyRunnable implements Runnable {
 2     private int ticket = 10;// 共10张票
 3     @Override
 4     public void run() {//所有的线程从此处执行
 5         for (int x= 0; x<10; x++)
 6             System.out.println(java.lang.Thread.currentThread().getName() + ",x = " + x);//取得线程名字
 7     }
 8 }
 9 public class TestRunnable {
10     public static void main(String[] args) {
11         MyRunnable mt = new MyRunnable();
12         new java.lang.Thread(mt).start();
13         new java.lang.Thread(mt).start();
14         new java.lang.Thread(mt,"有名字").start();
15     }
16 }

 

执行结果:

Thread-0,x = 0
有名字,x = 0
有名字,x = 1
有名字,x = 2
Thread-0,x = 1
有名字,x = 3
Thread-1,x = 0
有名字,x = 4
Thread-0,x = 2
有名字,x = 5
Thread-1,x = 1
有名字,x = 6
Thread-0,x = 3
有名字,x = 7
Thread-1,x = 2
有名字,x = 8
Thread-0,x = 4
有名字,x = 9
Thread-1,x = 3
Thread-0,x = 5
Thread-1,x = 4
Thread-0,x = 6
Thread-1,x = 5
Thread-0,x = 7
Thread-1,x = 6
Thread-0,x = 8
Thread-1,x = 7
Thread-0,x = 9
Thread-1,x = 8
Thread-1,x = 9

 

注:设置名字不能重复,同时中间不能修改

主方法直接调用和启动线程调用run的区别:

 1 class MyRunnable implements Runnable {
 2     private int ticket = 10;// 共10张票
 3     @Override
 4     public void run() {//所有的线程从此处执行
 5         System.out.println(java.lang.Thread.currentThread().getName());
 6     }
 7 }
 8 public class TestRunnable {
 9     public static void main(String[] args) {
10         MyRunnable mt = new MyRunnable();
11         mt.run();//直接通过对象调用
12         new java.lang.Thread(mt).start();//通过线程调用run
13     }
14 }

 

执行结果:

main   Thread-0

 

可以知道:主方法本身就是一个线程,所有的线程都是通过主线程创建并启动的

五、线程休眠

       线程休眠是指让线程暂停执行一段时间后再次执行,方法:public static void sleep(long millis)throws InterruptedException,休眠时间使用毫秒作为单位。休眠操作实现如下:

 1 class MySleep implements Runnable{
 2     @Override
 3     public void run() {
 4         for (int x = 0; x < 20; x++){
 5             try {
 6                 java.lang.Thread.sleep(1000);//休眠一秒
 7             }catch (InterruptedException e){
 8                 e.printStackTrace();
 9             }
10             System.out.println(java.lang.Thread.currentThread().getName() + ",x = " + x);
11         }
12     }
13 }
14 public class TestSleep {
15     public static void main(String[] args) {
16         MySleep mt = new MySleep();
17         new java.lang.Thread(mt).start();
18         new java.lang.Thread(mt).start();
19         new java.lang.Thread(mt).start();
20     }
21 }

 

注:并不是三个一起执行的,而是代码依次进入run()方法,并发执行

六、线程的优先级

       优先级越高越可能先执行,但不是一定先执行

设置优先级方法:public final void setPriority(int newPriority)

取得优先级方法:public final int getPriority

设置优先级可以通过Thread类的几个常量来确定:

最高优先级:public static final int MAX_PRIORITY、10(常量的值)

中等优先级:public static final int NORM_PRIORITY、5

最低优先级:public static final int MIN_PRIORITY、1

设置优先级实现如下:

 1 class MyPrority implements Runnable{
 2     @Override
 3     public void run() {
 4         for (int x = 0; x < 2; x++){
 5             System.out.println(java.lang.Thread.currentThread().getName() + ",x = " + x);
 6         }
 7     }
 8 }
 9 public class TestSetPrior {
10     public static void main(String[] args) throws Exception{
11         //查看主方法的优先级
12         System.out.println(java.lang.Thread.currentThread().getPriority());
13         MyPrority mt = new MyPrority();
14         java.lang.Thread t1 = new java.lang.Thread(mt,"线程A");
15         java.lang.Thread t2 = new java.lang.Thread(mt,"线程B");
16         java.lang.Thread t3 = new java.lang.Thread(mt,"线程C");
17         t1.setPriority(java.lang.Thread.MIN_PRIORITY);
18         t2.setPriority(java.lang.Thread.MAX_PRIORITY);
19         t3.setPriority(java.lang.Thread.NORM_PRIORITY);
20         t1.start();
21         t2.start();
22         t3.start();
23     }
24 }

 

执行结果为:可以知道主方法的优先级为中等优先级,最先执行的为B(最高优先级),然后是C(中等优先级),最后才是C(最低优先级)

5
线程B,x = 0
线程C,x = 0
线程B,x = 1
线程C,x = 1
线程A,x = 0
线程A,x = 1

 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Set集合中的treeSet问题:cannot be cast to java.lang.Comparab

下一篇:JAVAEE——Solr:安装及配置、后台管理索引库、 使用SolrJ管理索