您的位置:首页 > 职场人生

黑马程序员_6_简单创建多线程

2014-08-02 20:08 211 查看

黑马程序员——简单创建多线程

-------
android培训、java培训、期待与您交流! ----------

多线程:在一个进程中有多个执行路径。
进程是正在运行的应用程序作为一个进程,进程中一个执行路径是一个线程<负责代码执行>。
说到这里很多人都会有一个疑问,线程是负责代码的执行,有时我们没创建线程,为什么代码一样可以执行呢?
因为一个java的应用程序,至少有俩个线程,都是jvm创建的,一个是主线程,负责main的代码执行,同时还会创建一个垃圾回收器线程, 负责垃圾回收。

那么多线程的优点:
1、可以在进程中同时执行多个任务代码。
2、提高了资源的利用率。而不是效率...

多线程的弊端:
1、增加了cpu的负担。
2、降低了一个进程线程的执行概率,
2、会出现线程安全问题。
3、引发了死锁问题。

说了这么多了,那怎么自定义线程呢?
sun公司给我们提供了一个线程基类Thread
步骤1:自定义一个类继承Thread
2:重写Thread里面run()方法,把自定义线程的代码放入run()方法中。
3:创建线程对象,调用start方法开启线程任务,线程一旦开启就会自动调用run()方法执行里面的代码。

注意:run方法不能直接的调用,如果直接调用了run方法,那么没有开启一个新的线程 ,只是相当于调用另一个普通方法而已。一定要调用start方法开启一个线程,线程启动时就回去执行run方法的代码了。

说了这么多了,那我们就来自定义一个多线程吧。

class MyThread extends Thread{//声明一个类继承线程Thread类

//重写run()把自定义线程执行的代码放入其中

public void run(){

for(int i=0;i<1000;i++){

System.out.println("自定义线程执行了..."+i);

}

}

}

class Demo1{

public static void  main(String[] args){

//创建线程对象

MyThread my = new MyThread();

//调用start方法开启线程。

my.start();

 }

}

[/code]

当我们再来使用多线程模拟车站售票时,却发现事没那么简单。

package cn.chen.thread;

//模拟车站卖票。。

class SaleTicket extends Thread{

//必须用静态修饰,因为保证3个窗口使用同一份数据。非静态成员变量会在每创建一个对象维护一份。

static int tickets=50;

//使用锁对象的时候,多个线程必须是使用同一个锁对象。
static Object o = new Object();

public SaleTicket(String name){

super(name);

}

public void run(){

while(true){

//锁对象是任意的对象,但必须保证同一份...

synchronized (o){

if(tickets>0){

System.out.println(Thread.currentThread().getName()+"卖出第"+tickets+"张票");

tickets--;

}else{

System.out.println("票已经售馨...");

break;

}

}

}

}

}

public class Demo3 {

public static void main(String[] args) {

//创建线程对象

SaleTicket st1 = new SaleTicket("一号窗口");

SaleTicket st2 = new SaleTicket("二号窗口");

SaleTicket st3 = new SaleTicket("三号窗口");

//开启线程

st1.start();

st2.start();

st3.start();


}

}

[/code]

楼上这个例子必须注意:使用同步代码块是为了解决线程安全问题,防止出现卖票错乱,在同步代码块中的锁对象,多个线程必须是使用同一个锁对象。没有线程安全,不建议使用同步机制,因为会降低操作效率。

同步机制的方式有两种:
同步代码块:
格式:
synchronized(锁对象){
需要被同步的代码...
}
注意:任何的对象都可以作为一个锁对象。

同步函数:
格式:
修饰符 synchronized 返回类型 函数名(){

}
定义实例如下:

public static synchronized void getMoney(){ //关闭
while(true){
//synchronized (o) {
if(count>0){
System.out.println(Thread.currentThread().getName()+"取走了一千块,账户的总额还剩余:"+ (count-1000));
count-=1000;
}else{
System.out.println("账户的余额不足...");
break;
}
//}
}

同步函数需要注意的细节:
1、如果是非静态函数锁对象是this对象,而且同步函数锁对象是不能更改的。
2、如果是静态函数中锁对象是当前函数所属类文件对象
大家都知道使用锁同步时,每个线程使用的锁必须是同一个,所以切记以上2点细节。

推荐使用同步代码块。因为锁可以任意,可以指定同步代码,很灵活。

自定义线程还有一种方法就是实现Runnable接口。重写run方法,
具体步骤如下:
1、自定义类实现Runnable接口,实现接口中run方法。把自定义线程任务写在run方法中。
2、创建Runnable实现类对象。
3、创建线程Thread对象,把Runnable实现类对象作为参数传递给线程Thread。
4、调用Thread中start方法开启线程。
同样是卖票,用实现Runnable接口又如何呢? 且看代码:

public class Demo6 {

public static void main(String[] args) {

//创建实现类对象。

TickThread t = new TickThread();

//创建线程3个。把实现类对象传递到线程

Thread thread1 = new Thread(t,"一号窗口");

Thread thread2 = new Thread(t,"二号窗口");

Thread thread3 = new Thread(t,"三号窗口");

  //调用start方法开启线程。

thread1.start();

thread2.start();

thread3.start();

}

}

class TickThread implements Runnable{

//这里就不需要static修饰了,因为只创建一个此类实例对象。

int ticks=50;


public void run(){

synchronized ("哈哈"){

	while(true){


if(ticks>0){

	System.out.println(Thread.currentThread().getName()+"售出"+ticks+"张票");

	ticks--;

}else{

System.out.println("票已经售馨...");

break;

}

}

}

}

}

[/code]

推荐使用:实现Runnable接口的方式。 因为java是单继承语言,如果自定义还需要有其他操作,继承了Thread很有局限。

注意:Runnable实现类的对象其实并不是一个线程对象,只是实现了Runnable接口类的对象而已。
只有是Thread或者Thread的子类才是一个线程对象。

在调用Thread对象的start方法开启一个线程的时候,那么Thread对象就会去执行自己类中的run方法,其实这内部调用了Runnable的实现类的run方法,换菊花说实际上是把Runnable实现类的run方法作为了Thread对象的任务代码去执行了。

-------
android培训、java培训、期待与您交流! ----------

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