java线程知识点拾遗(1)

作为一个android开发者的我来说,面试最怕问的问题就是问多线程方面的,问之必死~~。因为android monkey在开发中多线程开发的场景使用起来几乎没有,所以就滋生了自己的懒惰性,人家说哪里跌倒哪里爬起来,这工作几年了也没爬起来,有点小羞愧。于是准备抽点时间好好研究下这个东东。
不要逼我,逼急了我什么都能做出来! 来来来,现场手写一个自旋锁出来试试!卒!

在多线程的编程中,如果需要加锁的情况下,通常需要synchronized来搞定(当然这是最初级的用法)用来确保线程安全,比如HashTable这个在开发中没怎么用过的组件,看其源码可以发现其public方法都加了synchronized来搞定;所以说HashTable是线程安全的。

在我们处理多线程并发的时候可能会经常这么写(这也是wait和notify notify All的正确使用姿势):

Object lock = new Object();
synchronized (lock) { 
    while (condition is not ok) { // 条件不满足,当前线程阻塞等待
         lock.wait(); 
    } 
    // 执行条件满足时的逻辑
    doSomething();
    // 通知阻塞的线程可以唤醒
    lock.notify();
}

简单举一个例子来说明,以前博主面试遇到过这个问题:两个线程交替打印奇数和偶数。
思路也很简单,因为是线程交替执行,所以当前数字是偶数的时候就让奇数线程wait,当前数字是奇数的时候就让偶数线程wait

打印奇数的线程

private Object lock = new Object();
private int i = 0;

  // 打印奇数
	class PrintOdd implements Runnable {
		@Override
		public void run() {
			synchronized (lock) {
				while (i <= 40) {
					if (i % 2 == 1) {
						System.out.println("打印奇数==" + i);
						i++;
						//通知偶数线程工作
						lock.notify();
					} else {
					   //当前是偶数,线程等待
						try {
							lock.wait();
						} catch (InterruptedException e) {

						}
					}

				} // end while

			} // end synchronized

		}//end run 

	}

打印偶数线程:


	class PrintEven implements Runnable {
		@Override
		public void run() {
			synchronized (lock) {
				while (i <= 40) {
					if (i % 2 == 0) {
						System.out.println("打印偶数************  " + i);
						i++;
						//通知奇数线程
						lock.notify();
					} else {
						try {
							lock.wait();
						} catch (InterruptedException e) {

						}
					}

				} // end while

			} // end synchronized

		}//end run 
		
	}

上面就是简单的利用了wait和notify方法,其实还有一个更简单的写法,如下所示:

volatile  boolean printOdd=true;
   private int i=0;
	// 打印奇数
	class PrintOdd implements Runnable {
		@Override
		public void run() {
			while(i<40) {
				if(printOdd) {
					System.out.println("打印奇数---------------"+i);
					i++;
					//开始打印偶数
					printOdd=false;
				}
			}
		}

	}

	class PrintEven implements Runnable {
		@Override
		public void run() {
			while(i<40) {
				if(!printOdd) {
					System.out.println("打印偶数*********"+ i);
					i++;
					//开始打印奇数
					printOdd=true;
				}
			}
			
		}// end run

	}

甚至可以把上面的i用AtomicInteger来替换,那么代码就如下所示:

   volatile  boolean printOdd=true;
   private AtomicInteger i=new AtomicInteger();
	// 打印奇数
	class PrintOdd implements Runnable {
		@Override
		public void run() {
			while(i.get()<4000) {
				if(printOdd) {
					System.out.println("打印奇数---------------"+i.getAndIncrement());
					//开始打印偶数
					printOdd=false;
				}
			}
		}

	}

	class PrintEven implements Runnable {
		@Override
		public void run() {
			while(i.get()<4000) {
				if(!printOdd) {
					System.out.println("打印偶数*********"+ i.getAndIncrement());
					
					//开始打印奇数
					printOdd=true;
				}
			}
			
		}// end run

	}
发布了257 篇原创文章 · 获赞 484 · 访问量 144万+

猜你喜欢

转载自blog.csdn.net/chunqiuwei/article/details/98875338