多线程编程
来源:互联网 发布:swift 商城源码 编辑:程序博客网 时间:2024/03/29 09:49
A基本概念
首先必须强调程序,进程,线程三个概念的联系和区别。程序,是存储于磁盘之中的代码序列,进程是一个程序在自身地址空间中的一次执行,一个程序可以有多个进程,比如我们可以同时打开多个windows的记事本,这就是记事本程序的多个进程。线程是进程中的一个单一的连续控制流,一个进程允许有多个线程。线程之间的信息交换将快于进程,这是必须记住的。
B。线程类
在JAVA的虚拟机中(JVM),要实现一个程序的多线程有两种方法,一是实现Runnable接口,该接口中唯一函数是run();二是继承自Thread类。这两个方法的实质是实现Runnable接口,因为Thread类就是实现了Runnable接口。另,Thread类在java.lang包下。
我们来分开讲述:
一。继承自Thread类,常用的函数如下:(非静态函数未注明)
1. currentThread()静态函数,可以获得当前运行的线程对象
2. getName(),获得线程的名字;
3.run(),线程运行时会运行该函数中的内容,一般要重写
4.setDaemon(boolean pa),pa为真时将线程设置为后台运行,必须在start()执行之前设置;
5.start(),线程对象开始运行
6.yield(),线程放弃运行,让其他程序运行
7.setPriority(int i),设置线程优先级,级数为1-10,默认优先级为5
8.sleep(long l)让线程暂停指定毫秒
9.interrupt(),中止线程。
此外,有 wait()和notify(),是来自java.lang.object类中,下文会另有篇幅详细叙述。
JVM支持不同优先级的线程抢占,但是它实质上是不支持相同优先级的时间片轮转的,要实现相同优先级的线程的时间片轮转,必须依赖于JVM当前的操作系统平台。如果当前的操作系统支持相同优先级线程的时间片轮转,则JVM可以支持相同优先级线程的时间片轮转,否则,不能支持。
二。实现Runnable接口,该接口有且只有一个方法run();事实上,Thread类实现了这个接口。
这里遇到了一个麻烦,因为JAVA不支持类的多继承,如果某一个线程类已经存在基类(super),那么他将无法再继承Thread类,但是有一个解决的方法,即依赖于内部类的继承来实现,这很显然会给我们对代码的控制造成影响,因此采用实现Runnable接口方式会更加的方便。但是这也要依照情况而论,毕竟Thread类中提供了很多有用的方法。
C.线程的同步
若多个线程要与某个对象关联,如果控制呢?我们设想以下情况,有线程a和b,要关联对象x,由于a和b是各自独立的,因此他们对x的修改都会对另一个造成影响,这势必造成混乱。我们必须限制当a访问x时候,b不能访问x,而当b访问x的时候,a同样不能访问x,即在某一个时刻,只能允许一个线程来访问x。
在java中提供了synchronized语法。有两种使用方式
一。Synchronized(任意对象)
{
语句
}
即同步块,可以和任意对象关联
二。 将某个方法声明为synchronized,即同步方法,这个方法与this指向的对象关联。因此,要实现同步块和同步方法之间也同步,必须让同步块关联到this,synchronized(this)。
在JVM中,任意对象都有一个等待队列和一个监视器(monitor),同一时刻只能有一个线程将这个监视器"锁住",其他线程试图进入该对象,则必须等待,进入等待队列,直到监视器被“松开”。这里要用到Object类中的wait()和notify()方法 。 wait()可以让某个线程对象进入等待队列,而notify()方法则从等待队列中取出某一个线程,该线程也不能马上运行,而必须等到监视器被“松开”。另还有notifyAll(),可以取出等待队列中的所有线程。注意,wait()和notify()必须是对在一个同步块中的对象使用。
D。线程的死锁。
设想以下情况,线程a和b,对象X和Y,a和b都要关联对象XY,在某个时刻,a已经锁住X的监视器,此时由于某种情况(如sleep()或者wait()),它被暂停而b得到运行,b会锁住Y的监视器,并等待a的监视器被“松开”。之后,a得以继续运行。这样陷入了尴尬的局面,a在等待Y的监视器,而b则在等待X的监视器,他们两各不相让,相持直到太阳变成超星星并爆炸毁灭地球都不会停止。这就是所谓死锁,在多线程编程时一定要避免这种情况。
以下是我写的一个生产者_消费者(Producer_Comsumer)模式的程序,期间出现了一个问题,即程序的打印结果出来以后,程序的运行还是没有停止。后来我发现,当main()退出以后,消费者线程仍然处于Queue的等待队列中,因此程序没有停止,我不得不在61行使用了Thread.currentThread().interrupt();来强制终止它。我相信随着我的练习,我会写出更加优美的语句。该程序在jdk1.5下运行通过,并可以完美退出。
class PCTest
{
public static void main(String[] args)
{
int i=0;
i++;
Queue que=new Queue();
Producer pro=new Producer(que);
Comsumer com=new Comsumer(que);
try
{
pro.start();
}
catch(IllegalThreadStateException e)
{
e.printStackTrace();
}
try
{
com.start();
}
catch(IllegalThreadStateException e)
{
e.printStackTrace();
}
}
}
class Queue
{
int i=0;
int num;
boolean flag=false;
synchronized void putNum(int num)
{
if(flag==false)
{
this.num=num;
System.out.println("The Producer has produced "+num);
this.flag=true;
notify();
try
{
wait();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
synchronized void getNum()
{
i++;
if(flag==true)
{
System.out.println("The Comsumer has comsumed "+num);
flag=false;
notify();
if(i==10)
{
Thread.currentThread().interrupt();
}
else
{
try
{
wait();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
}
class Producer extends Thread
{
Queue que;
Producer(Queue que)
{
this.que=que;
}
public void run()
{
for(int i=0;i<10;i++)
{
que.putNum(i);
}
}
}
class Comsumer extends Thread
{
Queue que;
Comsumer(Queue que)
{
this.que=que;
}
public void run()
{
for(int i=0;i<10;i++)
{
que.getNum();
}
}
}
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 多线程编程
- 迷宫最短路径算法(使用队列)
- 雅思复习计划
- “阿里外传”之一:阿里巴巴有只宠物,叫雅虎
- 写点程序以外的事情,最近又打了好几盘魔兽了,终究是自己深深热爱的游戏,而且这几天还在看电视剧一刚!
- PE转换为IMAGE映象工具的源码
- 多线程编程
- SQL中All, Any, Some的意思
- 心情日记
- 关于以后 WEB 开发的一个想法
- Java工厂方法模式设计
- CG简介
- 关于以后 WEB 开发的一个想法(2)
- 关于以后 WEB 开发的一个想法(3)
- observe the real world