您的位置:首页 > 其它

多线程

2016-03-14 19:55 288 查看
如果要想进行多线程的开发,则和程序的主类一样,线程也需要一个线程的主体类。但是所有的线程主体类有两种定义的形式:一种是继承Thread类,另外一种是实现Runnable接口。很明显按照面向对象的概念来讲解使用Runnable接口会更加的合适,因为避免了单继承局限。

继承Thread类

Thread类是线程操作之中最为重要的一个类,如果要定义线程主体类,直接继承此类,同时覆写此类之中的run()方法即可,而run()方法就相当于是线程中的主方法一样

范例:定义线程主体类

class MyThread
extends Thread {
private String
title ;
public MyThread(String title) {
this.title = title ;
}
@Override
public
void
run() {
for (int x = 0; x < 10; x++) {
System.out.println(this.title +
",x = " + x);
}
}
}

线程主体类一旦定义完成之后,如果要想启动多线程,肯定首先要实例化MyThread类的对象,而后调用里面的方法,可是这个时候不能够直接调用run()方法,因为run()方法只是定义了线程的功能,但并不表示启动线程,如果要想启动线程,则必须利用Thread类中的start()方法完成:public
void start()


启动多线程

public
class
TestDemo {
public
static void
main(String[] args) {
MyThread mt1 = new MyThread("线程A");
MyThread mt2 = new MyThread("线程B");
MyThread mt3 = new MyThread("线程C");
mt1.start();
mt2.start();
mt3.start();
}
}
可以发现现在所有的线程都在交替运行状态下执行。就证明了,多个线程互相抢占CPU的资源。

实现Runnable接口

多线程主体类的另外一种实现方式是采用了Runable接口,可以避免单继承的局限。

范例:通过Runnable实现线程主体类

class MyThread
implements Runnable {
private String
title;
public MyThread(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
TestDemo {
public
static void
main(String[] args) {
MyThread mt1 = new MyThread("线程A");
MyThread mt2 = new MyThread("线程B");
MyThread mt3 = new MyThread("线程C");
new Thread(mt1).start();
new Thread(mt1).start();
new Thread(mt2).start();
new Thread(mt3).start();
}
}

结论:不管是何种方式实现的多线程,都必须通过Thread类的start()方法启动。

多线程的两种实现方式联系与区别

对于多线程的两种实现方式如果从代码结构上讲肯定使用Runnable接口要比使用Thread类更加合适,因为可以避免单继承的局限,但是除了这点区别之外,Runnable接口和Thread类之间实际上还是会存在联系的。

Thread类的继承结构。

public class Thread extends Object implements Runnable

发现Thread类实际上就是Runnable接口子类。那么对于此时的程序结构如下。



区别:使用Runnable实现的多线程要比使用Thread类实现多线程具备更明显的数据共享优势。数据共享指的是多个线程操作同一资源的情况。

范例:利用Runnable实现(Runnable里面没有start()方法,必须借助于Thread类启动)

package cn.mldn.test;
class MyThread
implements Runnable {
private
int
ticket = 5 ;
// 一共5张票
@Override
public
void
run() {
for (int x = 0; x < 50; x++) {
if (this.ticket > 0) {
// 还有票
System.out.println("卖票,ticket = " +
this.ticket --);
}
}
}
}
public
class
TestDemo {
public
static void
main(String[] args) {
MyThread mt = new MyThread() ;
new Thread(mt).start();

new Thread(mt).start();

new Thread(mt).start();

}
}
此时定义了三个Thread类的对象,而且这三个类的对象同时占用了一个Runnable接口子类的对象引用,所以就表示这三个线程对象指向同一块空间,里面有ticket这个属性。

多线程的两种实现方式及区别

· 多线程可以继承Thread类或实现Runnable接口来定义;

· 使用Runnable接口可以避免单继承的局限,同时可以更好的表示出数据共享的概念。而Thread类是Runnable接口的子类,如果要想启动多线程一定需要Thread类的start()方法完成。

线程的命名和取得

构造方法:public Thread(Runnable target, String name);
设置名字:public final void setName(String name);

取得名字:public final String getName()。

MyThread mt = new MyThread() ;
new Thread(mt,
"线程A").start();
new Thread(mt).start();
new Thread(mt,
"线程B").start();
new Thread(mt).start();

实际上这个时候如果没有为线程对象设置名字,那么会由系统按照“Thread-xxx”的形式自动命名,以保证每一个线程都有自己独立的名字。

问题:请问每一个JVM进程至少启动几个线程?

两个:main、GC。

线程的休眠

如果现在希望让线程的每次执行放慢速度,则可以通过线程的休眠操作完成,操作的方法:

·休眠:public static void sleep(long millis) throwsInterruptedException,单位是毫秒。

class MyThread
implements Runnable {
@Override
public
void
run() {
for (int x = 0; x < 100; x++) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +
",x = " + x);
}
}
}

线程的优先级

由于所有的线程都要去抢占资源,所以理论上那个线程优先级高,那个线程就应该先执行,如果要想操作线程的优先级可以使用如下的两个方法完成:

·设置优先级:public final void setPriority(int newPriority);

·取得优先级:public final int getPriority()。

可以发现设置和取得优先级的时候所取得类型全部是数字,而对于这个数字可以通过如下的三个常量设置:

·最高优先级:public static final int MAX_PRIORITY,10;

·中等优先级:public static final int NORM_PRIORITY,5;

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

MyThread mt = new MyThread();
Thread t1 = new Thread(mt,
"线程A");
Thread t2 = new Thread(mt,
"线程B");
Thread t3 = new Thread(mt,
"线程C");
t1.setPriority(Thread.MIN_PRIORITY);
t3.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
t3.start();

既然主方法本身也是一个线程,那么主线程的优先级是什么呢?

public
class
TestDemo {
public
static void
main(String[] args) {
System.out.println(Thread.currentThread().getPriority());
}
}

主线程为中等优先级。

同步与死锁
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: