您的位置:首页 > 其它

多线程 消费者和生产者的问题

2011-07-18 03:51 253 查看
多线程在一个进程内虚拟出多个虚拟机它们共享或独享这个进程的一步份资源 独立或共同完成某一功能
多线程其实不是同时执行多个线程同一时间内只有一个线程执行知识CPU切换的线程的速度相当快 让我们误以为多个线程在同时工作 多线程的程序不一定比单线程的程序快
线程在某种意义上也可以理解为进程的进程 应为你如果把操作系统看做个进程的话那么进程可以看作为操作系统的线程
因为平凡切换线程也是要话费时间的 反过来单线程的程序不一定比多线程的程序快 比如单线程程序如果碰到人机交互的时候整个程序就会停下来等待用户的指令 而多线程可以单独指派若干个线程来操作人机互动的部分定外一部分来操作程序其余的部分
java程序其实默认就开了多线程 如swing/awt/时间监视器/垃圾制动回收机制等等都开了响应的线程来执行这些功能
设计不合理的多线程还不如不设计来的好知识浪费资源
线程分为守护线程和用户现场 守护线程随着进程的启动而启动启动以后在后台监视当满足执行条件的时候执行
线程的运行过程 首先JVM启动个主线程执行程序里的main方法 如果是多线程的话会由主线程创建线程,主线程和线程可以看成同时执行这点和单线程的多方法调用不同它是顺序的 多线程是并发的 当main方法结束主线程结束这是程序不会结束,只有结束了所有的用户线程程序才会结束了 具体执行哪个线程是随机的由线程调度器调度的不可控制的就跟垃圾自动回收机制一样所以不要想当然的哪个经常先执行而设计代码
以上的部分相对于进程和操作系统之间的流程基本相同 进程也分为守护进程和用户进程守护进程的功能一查不多
创建个线程可以创建个类extends Thread类 在创建个事例调用start方法 也可以implements Runnable类 在创建个事例包装成Thread 调用他的start方法
这2种方法创建的线程在有些时候功能不一样 主要体现着临界资源上 不过可以把临界资源改成Static来抵消区别 继承创建的线程是多个对象 实现创建的有可能是单个或多个对象
控制并发同步 主要用到synchronized关键字和wait ,notify,sleep 临界资源的灵活运用上 线程1wait()后立即释放同步锁这点跟sleep不同锁的对象如果相同如果在同步块内sleep不会释放同步锁,这样的后果就是相当于单线程的效果 其他所有的线程等着你 线程2调用notify时线程1醒来后不会获得同步锁这点有可能会造成并发不同步严重时线程崩溃或程序崩溃 下面的代码有掩饰
synchronized关键字放在方法里锁是调用这个方法的对象 跟放在代码快中synchronized(this)效果一样只是范围不同 这里的this可以改成所有的类 但是这个类要有执行new 行为不然编译会报错 只有调用这方法的对象专用同一内存空间时才是同一把锁 这里要小心死锁的问题如对象1要拿到对象2持有的锁对象2要拿到对象1持有的锁
死锁
class Demo{
public static void main(String[] args) {
Thread t1=new MyThread();
Thread t2=new MyThread();
t1.start();
t2.start();
}
}
class MyThread extends Thread{
private static boolean flag=true;
String a=new String();
String b=new String();
public void run(){
if(flag){
flag=false;
synchronized(a){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(b){}
}
}
synchronized(b){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(a){}
}
}
}
//消费者和生产者
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
class Demo1{
public static void main(String[] args) {
//如果它们是继承的Thread类的话就可以写成 XiaoFei1=new XiaoFei1(ms);
MyStack ms=new MyStack();
Thread xf1=new Thread(new XiaoFei1(ms));
Thread xf2=new Thread(new XiaoFei2(ms));
Thread sc1=new Thread(new ShenChan1(ms));
Thread sc2=new Thread(new ShenChan2(ms));
xf2.start();
xf1.start();

sc1.start();
sc2.start();
}
}
class XiaoFei2 implements Runnable{
private MyStack myStack=null;
public XiaoFei2(MyStack myStack){
this.myStack=myStack;
}
public void run(){
for(int i=0;i<50;i++){
System.out.println("消费者2"+" "+myStack.get("消费者2"));
try {
Thread.sleep(new Random().nextInt(301));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class XiaoFei1 implements Runnable{
private MyStack myStack=null;
public XiaoFei1(MyStack myStack){
this.myStack=myStack;
}
public void run(){
for (int i=0;i<50;i++){
System.out.println("消费者1"+" "+myStack.get("消费者1"));
try {
Thread.sleep(new Random().nextInt(301));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class ShenChan2 implements Runnable{
private MyStack myStack=null;
public ShenChan2(MyStack myStack){
this.myStack=myStack;
}
public void run(){
for(int i=0;i<50;i++){
char c=(char)(new Random().nextInt(26)+'a');
System.out.println("生产者2"+" "+c);
myStack.add(c);
try {
Thread.sleep(new Random().nextInt(301));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class ShenChan1 implements Runnable{
private MyStack myStack=null;
public ShenChan1(MyStack myStack){
this.myStack=myStack;
}
public void run(){
for (int i=0;i<50;i++){
char c=(char)(new Random().nextInt(26)+65);
System.out.println("生产者1"+" "+c);
myStack.add(c);
try {
Thread.sleep(new Random().nextInt(301));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyStack{
private List lst=new ArrayList();
public synchronized Object get(String str){
Object obj=new Character('无');
if (lst.size()==0){
try {
System.out.println(str+"==========>is wait");
wait();
//最后加的 当生产者线程执行notify时 执行wait的线程醒来以后如果轮到它运行的话将不执行维护临界资源
//的代码而是递归从新获取同步锁 当递归返回时接着执行return null;不然的话还是有可能出现问题
//可以在外面判断如果返回null重复执行一遍get方法
get(str);
return "null";
} catch (InterruptedException e) {
System.out.println(str+"========>bad");
e.printStackTrace();
}
}//else{
//如果这部分代码不放到else里面定一个消费者线程没有在wait()状态下生产者线程执行了notify();以后
//List集合里面只有一个数据的时候它从wait()状态醒来这时不会获得同步锁如果线程调度器先后指定消费者
//1或2执行的话那么其中一个将会执行lst.get(-1);将导致该线程崩溃但程序不会崩溃不过该情况的出现要看
//点子 如果把if改成while也是一样只是出错的几率会小点
obj=lst.get(lst.size()-1);
lst.remove(lst.size()-1);
// }

return obj;
}
public synchronized void add(Object obj){
lst.add(obj);
notify();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: