`
lujinglong
  • 浏览: 10711 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

多线程

阅读更多
1.多个线程共享系统提供给进程的同一块内存地址空间。

2.实现多线程程序的两种方式:
(1)从Thread类继承
(2)实现Runnable接口,实现run()方法。Thread(Runnable target)---Thread(Runnable target,String name)
同样我们也可以使用内部类的方式隐藏实现细节,定义为private.再定义一个getThread()方法获得该内部类的实例,因为一个内部类可以访问外部所有的成员。那么我们同样可以使用这种方式同时启动多个线程访问同一个变量。这样外部类就可以继承别的类或者实现别的接口。应用:例如售票系统。

3.后台线程
JVM会有一个线程执行Main方法。CurrentThread()返回一个static Threan,获取当前的线程。getName()获取线程的名字。定义一个类,继承Thread,执行一段代码,子类要覆盖父类的run()方法,public void 类型的run()方法。在main方法中创建该线程类的实例,调用start()方法。

4.在继承父类Thread的子类中可以自己创建构造方法,传入参数,定义线程的名字。

5.要把某线程类设置成后台线程,可以调用setDaemon()设置成后台线程。true变量设置为后台线程。当一个进程当中,没有非后台线程运行,那么该程序就结束了。yield()使当前线程对象临时暂停,允许别的线程执行,这是一个静态的方法。

6.getPriority(int newPriority),setPriority(int newPriority)得到线程的优先级和设置。MAX_PRIORITY==10,MIN_PRIORITY==1,NORM_PRIORITY==5,三个常量都是一个整数,那么他们的值是,1~10是正常的值。

7.JAVA是抢占式的线程调度模型,有自己的线程调度器。JAVA语言本身不实现相同优先级的时间片轮换,如果JAVA运行所在的系统支持时间片轮换,那么就可以进行时间片轮换。

8.从Thread类继承而来的线程类,在创建该线程类的对象时候,每个对象都有各自的一份拷贝,对访问同一个资源的功能而言,extends Thread不适用。

9.声明一个内部类继承于Thread,则该内部类可以访问外部类的任何成员。我们可以用一个自定义的getNewInstance()方法,获得该内部类的实例。返回return new InnerClassThread();

10.public class SellThread implements Runnable {

int tickets =100;
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
if(tickets>0){
System.out.println(Thread.currentThread().getName()+"Sell Tickets:"+tickets);
tickets--;
}
}

}
}

public class TicketSystem {
public static void main(String args[]){
SellThread st = new SellThread();//只能声明一个SellThread实例,然后使用该实例创建出四个线程,这四个线程访问的才是同一个共享的变量tickets
new Thread(st).start();
new Thread(st).start();
new Thread(st).start();
new Thread(st).start();
}


}


11.线程类方法sleep(1000)---让线程休息一会,1000毫秒,就是1秒。

12.线程的同步。可以解决多线程访问同一变量后,出现的问题。
在以上代码中,在run()方法中的代码,我们必须先让一个线程执行完该方法内的if()语句块中的所有代码,我们才让另外一个线程进入该代码块中执行该段代码。
(1)The code segments within a program that access the same object from separate, concurrent threads are called “critical sections”。
在一个程序当中,代码段从单独的并发当中访问了同一个对象,那么该代码段我们称为临界区。【我们就要采用同步的机制对该代码段进行保护】
(2)同步的两种方式:同步块和同步方法
public class SellThread implements Runnable {

int tickets =100;
Object obj = new Object();
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
synchronized(obj){ //判断Obj中个对象的监视器是否被加锁,如果没有被加锁,那么就会将obj加锁,然后往下执行。
//当该代码段被加上锁以后,后面的线程就不可以进入该代码段,知道前一个线程执行完该代码段后,并给该代码段解锁。以此类推
if(tickets>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"Sell Tickets:"+tickets);
tickets--;
}
}

}

}
}
(3)每一个对象都有一个监视器,或者叫做锁
(4)同步方法利用的是this所代表的对象的锁
(5)每个class也有一个锁,是这个class所对应的Class对象的锁
同步静态方法,利用的是该静态方法所在的这个类所对应的监视器。

13.死锁:哲学家进餐问题。
注意suspend()和resume()方法。容易造成死锁。

14.wait(),notify(),notifyAll()管理生产者和消费者问题。
(1)每一个对象除了有一个锁之外,还有一个等待队列(wait set),当一个对象刚创建的时候,它的对待队列是空的。wait()方法只能在同步方法当中或者同步块当中被调用。
(2)我们应该在当前线程锁住对象的锁后,去调用该对象的wait方法。
(3)当调用对象的notify方法时,将从该对象的等待队列中删除一个任意选择的线程,这个线程将再次成为可运行的线程。
(4)当调用对象的notifyAll方法时,将从该对象的等待队列中删除所有等待的线程,这些线程将成为可运行的线程。
(5)wait和notify主要用于producer-consumer这种关系中。

15.线程的状态

stop()-suspend()-该两方法不建议使用。

16.线程的终止
(1)设置一个flag变量。
(2)结合interrupt()方法。
public class TestThread {
public static void main(String[] args){
Thread1 t1 = new Thread1();
t1.start();
int index = 0;
while(true){
if(index++==500){
t1.stopThread(); t1.interrupt(); break;
}
System.out.println(Thread.currentThread().getName());
}
System.out.println("main() exit!");
}
}

class Thread1 extends Thread{
private boolean tsflag = false;
public void run(){
while(!tsflag){

try {
wait();
} catch (Exception e) {
if(tsflag){
return;
}
}



System.out.println(getName());
}
}
public void stopThread(){
tsflag = true;
}

}
  • 大小: 89.2 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics