现在的位置: 首页 > 综合 > 正文

java-线程

2013年04月27日 ⁄ 综合 ⁄ 共 5427字 ⁄ 字号 评论关闭

线程:是一个程序里面不同的执行路径
进程:一个class文件,一个exe文件,静态的概念,进程的执行指的是进程里面的主线程,main方法执行了,实际上都是线程在执行
        同一个时间点上,一个cpu只能支持一个线程在执行

两种方式创建线程:1.继承thread(只能是单继承较狭隘)

                          

class Runner2 extends Thread{
	public void run() {
	}
	
}
new Runner2().start();

                         2.实现runnerable

class Runner1 implements Runnable {
	public void run() {
	}

}

new Thread(new Runner1()).start()

一些常用到的方法属性:
sleep:休眠(并不释放锁)
join:合并线程(相当于方法调用)
yield:让出小会儿给别人执行

线程的优先级

Object.wait():(让正在访问此代码块的线程等待一下,让别的线程继续运行)调用此方法时,必须锁定该对象
Object.notify():(叫醒正在访问此代码块的单个线程)

Object.notifyAll():(叫醒正在访问此代码块的所有线程)

synchronized:线程同步(锁定当前内容,同一时间只有一个线程访问它):
      

        /**
	 *放在方法上
         */
      public synchronized void add(String name){
            num ++;
            try {Thread.sleep(1);}
            catch (InterruptedException e) {
            System.out.println(name+", 你是第"+num+"个使用timer的线程");
           }
        }
        /**
         *放在代码块中
	 */
        public void add(String name){
            synchronized (this) {
            num ++;
            try {Thread.sleep(1);}
            catch (InterruptedException e) {
            System.out.println(name+", 你是第"+num+"个使用timer的线程");
            }
            }
        }

 

死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生 了死锁,这些永远在互相等待的进程称为死锁进程。 由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁

        如果线程A锁住了记录1并等待记录2,而线程B锁住了记录2并等待记录1,这样两个线程就发生了死锁现象

View Code

package thread;

/**
 * 
 * @description
 *                    死锁的例子
 * @package name      
 *                    thread.DeadLock.java
 * @author            
 *                    lj
 * @since              
 *                    2012-4-8下午10:44:04
 */
public class DeadLock implements Runnable{
    int flag;
    static Object o1 = new Object();//注意是静态的,那样才是属于类独有的,不是属于对象的
    static Object o2 = new Object();
    
    public void run() {
        System.out.println("flag:" + flag);
        if(flag == 1) {
            synchronized (o1) {
                try{
                    Thread.sleep(500);
                }catch(Exception e){
                    e.printStackTrace();
                }
                
                synchronized (o2) {
                    System.out.println("  看到了此输出说明flag为1的线程完全执行了");
                }
            }
        }else{
            synchronized (o2) {
                try{
                    Thread.sleep(500);
                }catch(Exception e){
                    e.printStackTrace();
                }
                
                synchronized (o1) {
                    System.out.println(" 看到了此输出说明flag为2的线程完全执行了");
                }
            }
            
        }
        
    }
    
    public static void main(String[] args) {
        DeadLock dl1 = new DeadLock();
        dl1.flag = 1;
        DeadLock dl2 = new DeadLock();
        dl2.flag = 2;
        
        Thread t1 = new Thread(dl1);
        t1.start();
        Thread t2 = new Thread(dl2);
        t2.start();
    }
}

System.out.println(" 看到了此输出说明flag为1/2的线程完全执行了"); 始终没有执行,没有输出,出现了死锁

 

 

生产者消费者问题:

View Code

  1 package thread;
2
3 /**
4 *
5 * @description
6 * 生产者消费者问题
7 * @package name
8 * thread.ProducerConsumer.java
9 * @author
10 * lj
11 * @since
12 * 2012-4-8下午09:52:23
13 */
14 public class ProducerConsumer {
15 public static void main(String[] args) {
16 Basket bk = new Basket();
17 Producer p = new Producer(bk);
18 Consumer c = new Consumer(bk);
19 new Thread(p).start();
20 new Thread(c).start();
21 }
22 }
23 /**
24 *
25 * @description
26 * 馒头
27 * @package name
28 * thread.ProducerConsumer.java
29 * @author
30 * lj
31 * @since
32 * 2012-4-8下午09:52:46
33 */
34 class Bun {
35 int id;
36 public Bun(int id) {
37 this.id = id;
38 }
39
40 public String toString() {
41 return "第" + (id+1) + "个馒头";
42 }
43 }
44 /**
45 *
46 * @description
47 * 篓子
48 * @package name
49 * thread.ProducerConsumer.java
50 * @author
51 * lj
52 * @since
53 * 2012-4-8下午09:53:00
54 */
55 class Basket {
56 Bun[] buns = new Bun[5];
57 int index;
58 /**
59 * 生产馒头
60 * @author
61 * lj  
62 * @since
63 * 2012-4-8下午09:54:28
64 * @param b void
65 * 返回
66 */
67 public synchronized void add(Bun b) {//同步是防止生产者放了馒头,但是因为某些异常,index没有来得及加加,但是实际上框子的馒头个数可能超过了10,你还想放
68 while(index == buns.length) {
69 try {
70 this.wait();
71 } catch (InterruptedException e) {
72 // TODO Auto-generated catch block
73 e.printStackTrace();
74 System.out.println("生产馒头时候的等待异常");
75 }
76 }
77 this.notify();//不写表明已经是满的了,但不叫醒消费者,就放在那里
78 buns[index] = b;
79 index++;
80 }
81 /**
82 * 消费馒头
83 * @author
84 * lj  
85 * @since
86 * 2012-4-8下午09:54:50
87 * @return Bun
88 * 返回
89 */
90 public synchronized Bun get() {//同步是防止消费者拿了馒头,但是因为某些异常,indent没有来得及减减,但是实际上框子里可能没有馒头了,但是你还想拿
91 while(index == 0) {
92 try {
93 this.wait();
94 } catch (InterruptedException e) {
95 // TODO Auto-generated catch block
96 e.printStackTrace();
97 System.out.println("拿馒头时候的等待异常");
98 }
99 }
100 //用if出现了异常,程序会跳出if继续执行后面的语句,而while不会
101 /*if(index == 0) {
102 try {
103 this.wait();
104 } catch (InterruptedException e) {
105 // TODO Auto-generated catch block
106 e.printStackTrace();
107 }
108 }*/
109 this.notify();//假设index=6,不写表明已经拿完了,但不叫醒生产者,总是空着
110 index--;//前面的index指针已经加加了,但是我没有那个位置装馒头,所以取出馒头的索引得往下减(类比栈内存)
111 return buns[index];
112 }
113 }
114 /**
115 *
116 * @description
117 * 生产者
118 * @package name
119 * thread.ProducerConsumer.java
120 * @author
121 * lj
122 * @since
123 * 2012-4-8下午09:53:16
124 */
125 class Producer implements Runnable{
126 Basket bk;
127 public Producer(Basket bk) {
128 this.bk = bk;
129 }
130 @Override
131 public void run() {
132 for(int i = 0; i < 10; i++) {
133 Bun b = new Bun(i);
134 bk.add(b);
135 System.out.println("生产了" + b);
136 try {
137 Thread.sleep((int)Math.random()*1000);
138 } catch (InterruptedException e) {
139 // TODO Auto-generated catch block
140 e.printStackTrace();
141 System.out.println("生产异常");
142 }
143 }
144 }
145
146 }
147 /**
148 *
149 * @description
150 * 消费者
151 * @package name
152 * thread.ProducerConsumer.java
153 * @author
154 * lj
155 * @since
156 * 2012-4-8下午09:53:40
157 */
158 class Consumer implements Runnable {
159 Basket bk;
160 public Consumer(Basket bk) {
161 this.bk = bk;
162 }
163 @Override
164 public void run() {
165 for(int i = 0; i < 10; i++) {
166 Bun b = bk.get();
167 try {
168 Thread.sleep((int)Math.random()*1000);
169 } catch (InterruptedException e) {
170 // TODO Auto-generated catch block
171 e.printStackTrace();
172 System.out.println("消费异常");
173 }
174 System.out.println("拿走了" + b);
175 }
176 }
177
178 }

 

反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,当在一个线程对象上调用stop()方法时,这个线程对象所运行的线程就会立即停止,假如一个线程正在执行:synchronized void { x = 3; y = 4;} 由于方法是同步的,多个线程访问时总能保证x,y被同时赋值,而如果一个线程正在执行到x = 3;时,被调用了 stop()方法,即使在同步块中,它也干脆地stop了,这样就产生了不完整的残废数据。而多线程编程中最最基础的条件要保证数据的完整性,所以请忘记线程的stop方法,以后我们再也不要说“停止线程”了。而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果 很难检查出真正的问题所在。

suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此 时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就 会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用 wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程

抱歉!评论已关闭.