- 浏览: 426527 次
- 性别:
- 来自: 昆明
文章分类
最新评论
Java中Thread的使用、死锁以及生产者消费者问题详解
线程的创建主要有四种方式,一种是直接继承Thread实现,另一种是引用接口Runable。这两种创建的线程可以多次使用。也可以运用内部类实现接口的创建。但是用这种方法创建的线程只能用一次。以下就是线程的四种创建方式的相关代码:
- package java819;
- public class TestThread {
- public static void main(String[] args) {
- MyThread1 mt = new MyThread1();
- MyThread2 mt2 = new MyThread2();
- mt.start();
- new Thread(mt2).start();
- new Thread() {//内部类实现
- public void run() {
- for (int i = 0; i < 100; i++) {
- System.out.println("++++线程3++++++" + i);
- }
- }
- }.start();
- new Thread(new Runnable() {
- @Override
- public void run() {
- for (int i = 0; i < 100; i++) {
- System.out.println("******线程4****" + i);
- }
- }
- }).start();
- for (int i = 0; i < 100; i++) {
- System.out.println("******主线程****" + i);
- }
- }
- }
- /**
- *
- * 四种方法实现线程的创建,两种运用的是内部类 一种是实现接口,一种是继承线程
- *
- */
- class MyThread1 extends Thread {
- @Override
- public void run() {
- for (int i = 0; i < 100; i++) {
- System.out.println("++++线程一++++++" + i);
- }
- }
- }
- class MyThread2 implements Runnable {
- @Override
- public void run() {
- for (int i = 0; i < 100; i++) {
- System.out.println("-----线程二-------" + i);
- }
- }
- }
当想让线程暂时暂停,进入休眠状态,可以用Sleep实现,该方法是静态方法,可以直接被Thread引用。可以在方法中设置休眠的时间。下面通过一个例子来说明Sleep的用法
1 package java819;
2 import java.io.IOException;
3 import java.nio.CharBuffer;
4 public class TestSleep {
5 public static void main(String[] args) {
6 Runner r = new Runner();
7 Thread t1 = new Thread(r);
8 Thread t2 = new Thread(r);
9 t1.start();
10 t2.start();
11 }
12 }
13 class Runner implements Runnable {
14 @Override
15 public void run() {
16 for (int i = 0; i < 200; i++) {
17 if (i % 10 == 0 && i != 0) {
18 try {
19 Thread.sleep(1000); //Sleep的用法
20 } catch (InterruptedException e) {
21 e.printStackTrace();
22 }
23 }
24 System.out.println("——————————线程————————————" + i);
25 }
26 }
27 }
当想让一个线程先执行完再去执行另一个线程时,可以用Join方法将当前线程先执行完。下面通过一个例子来说明Join的用法。
- package cn.yj3g;
- public class TestJoin {
- public static void main(String[] args) {
- MyThread2 t1 = new MyThread2("zhangcun");
- t1.start();
- try {
- t1.join();//先执行调用join方法的线程对象的run方法,完成后才调用这条语句所在的线程
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- for (int i = 1; i <= 10; i++) {
- System.out.println("------i am main thread");
- }
- }
- }
- class MyThread2 extends Thread {
- MyThread2(String s) {
- super(s);
- }
- public void run() {
- for (int i = 1; i <= 10; i++) {
- System.out.println("I am " + getName());
- try {
- sleep(1000);
- } catch (InterruptedException e) {
- System.out.println("又被打爆了!");
- return;
- }
- }
- }
- }
当需要一个线程让出当前执行状态即CPU,给其他线程执行的机会,就需要使用Yield方法,使当前线程暂时阻塞,让程序去执行其他的线程。还是通过一个例子来说明。
1 package java819;
2 public class TestYield {
3 public static void main(String[] args) {
4 MyYield my1 = new MyYield();
5 MyYield2 my2 = new MyYield2();
6 my1.start();
7 my2.start();
8
9 }
10 }
11 class MyYield extends Thread {
12 @Override
13 public void run() {
14 for (int i = 0; i < 100; i++) {
15 System.out.println("数字为:" + i);
16 if (i % 10 == 0 && i != 0) {
17 yield();
18 }
19 }
20 }
21 }
22 class MyYield2 extends Thread {
23 @Override
24 public void run() {
25 for (int i = 0; i < 100; i++) {
26 System.out.println("线程二数字为:" + i);
27 if (i % 10 == 0 && i != 0) {
28 yield();
29 }
30 }
31 }
32 }
判断当前线程是否还在执行可以使用Thread.currentThread().isAlive()实现。
如果想让某一个线程的优先级优先,可以通过setPriority来设置线程的优先级。当然也会有一个getPriority来获取优先级MinPriority=1,MaxPriority=10,NomPriority=5。下面通过一个例子来说明setPriority的用法。
- package java819;
- public class TestPriority {
- public static void main(String[] args) {
- T1 t = new T1();
- T2 tt = new T2();
- tt.setPriority(Thread.NORM_PRIORITY + 4);//设置线程的优先级来改变线程的优先级
- t.start();
- tt.start();
- }
- }
- class T1 extends Thread {
- @Override
- public void run() {
- for (int i = 0; i < 100; i++) {
- System.out.println("线程T1" + i);
- }
- }
- }
- class T2 extends Thread {
- @Override
- public void run() {
- for (int i = 0; i < 100; i++) {
- System.out.println("--------线程T2" + i);
- }
- }
- }
如果想实现当一个线程在占用一个资源时,不让别的线程来抢占资源,可以使用synchronized来修饰方法或者语句块,这样别的线程就不会进入synchronized修饰的方法或者方法块。
wait()和sleep()的区别:
<1>wait()时别的线程可以访问锁定对象。
<2>调用该方法时必须锁定该对象。
<3>sleep()时别的线程不可以访问锁定对象。
如果两个线程互相占用对方资源,那么线程将会进入死锁状态,在实现线程时,应该尽量避免死锁情况。下面就是一个典型的死锁例子,在编程时,我们应该要避免死锁的发生。
死锁例子:
1 package java819;
2 public class TestDeadLock implements Runnable {
3 public int flag = 1;
4 static Object o1 = new Object(), o2 = new Object();
5 @Override
6 public void run() {
7 System.out.println("flag=" + flag);
8 if (flag == 1) {
9 synchronized (o1) {
10 try {
11 Thread.sleep(500);
12 } catch (Exception e) {
13 e.printStackTrace();
14 }
15 synchronized (o2) {
16 System.out.println("1");
17 }
18 }
19 }
20 if (flag == 0) {
21 synchronized (o2) {
22 try {
23 Thread.sleep(500);
24 } catch (Exception e) {
25 e.printStackTrace();
26 }
27 synchronized (o1) {
28 System.out.println("0");
29 }
30 }
31 }
32 }
33 public static void main(String[] args) {
34 TestDeadLock td1 = new TestDeadLock();
35 TestDeadLock td2 = new TestDeadLock();
36 td1.flag = 1;
37 td2.flag = 0;
38 Thread t1 = new Thread(td1);
39 Thread t2 = new Thread(td2);
40 t1.start();
41 t2.start();
42 }
43 }
通过以上所学的知识,我们就可以实现生活中常遇到的一个生产者消费者问题。下面我就通过一个实例来对这个问题进行下说明。
生产者消费者问题:
- package cn.yj3g;
- public class TestPC {
- public static void main(String[] args) {
- PizzaStack ps = new PizzaStack();
- Thread t1 = new Thread(new Cooker(ps));
- Thread t3 = new Thread(new Cooker(ps));
- Thread t5 = new Thread(new Cooker(ps));
- Thread t2 = new Thread(new Customer(ps));
- Thread t4 = new Thread(new Customer(ps));
- t1.start();
- t3.start();
- t2.start();
- t4.start();
- t5.start();
- }
- }
- /*
- * 厨子
- */
- class Cooker implements Runnable {
- PizzaStack ps;
- public Cooker(PizzaStack ps) {
- this.ps = ps;
- }
- @Override
- public void run() {
- ps.push();
- }
- }
- /*
- * 食客
- */
- class Customer implements Runnable {
- PizzaStack ps;
- public Customer(PizzaStack ps) {
- this.ps = ps;
- }
- @Override
- public void run() {
- ps.pop();
- }
- }
- /*
- * pizza
- */
- class Pizza {
- int id;
- public Pizza(int id) {
- this.id = id;
- }
- public String toString() {
- return "pizza "+id;
- }
- }
- /*
- * pizza筐
- */
- class PizzaStack { //栈
- private Pizza[] ps = new Pizza[10];
- int size;
- public void push() {
- while(size>=0 && size<ps.length) {
- synchronized (this) {//此语句块锁住
- this.notifyAll();//唤醒所有线程
- Pizza p = new Pizza(size);
- ps[size++] = p;
- System.out.println("+++++++生产了"+p+" 剩下"+size+"个");
- }
- try {
- Thread.sleep((long)(Math.random()*1000));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- try {
- synchronized (this) {
- wait();
- }
- } catch (InterruptedException e) {
- }
- push();
- }
- public void pop() {
- while(size>0 && size<=ps.length) {
- synchronized(this) {
- this.notifyAll();
- Pizza p = ps[--size];
- System.out.println("------消费了"+p+" 剩下"+size+"个");
- }
- try {
- Thread.sleep((long)(Math.random()*1000));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- try {
- synchronized (this) {
- wait();
- }
- } catch (InterruptedException e) {
- }
- pop();
- }
- }
以上就是有关线程的全部内容,在以后的编程中我们会经常用到线程,所以这方面的知识要牢牢掌握。
原文地址: http://www.cnblogs.com/zxl-jay/archive/2011/09/25/2189930.html
相关推荐
死锁and生产者消费者问题
java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁源码java死锁...
解决线程死锁问题的 生产者 消费者程序
读者写者问题是在生产者消费者问题的基础上改进而来,其不同点仅在于加入一个计数变量count来记录处于读写空间中读者的数量,实现读者可同时读文件。 银行家算法基于安全性算法实现,其目的是避免死锁方法中允许...
Java中死锁的例子,非常的例子。经过本人验证
操作系统中哲学家就餐问题和生产者消费者问题实验报告
java Thread Dump 其实就是stack trace。 我们平时经常会碰见java异常,并且得到异常的方法用e.printstacktrace 实际上程序正常运行时也是会有stack trace的,只不过平时不显示出来而已。如何能正常及时显示堆栈信息...
理解java中生产者消费者模型,以及如何利用双缓冲机制来解决同步与死锁问题。
java 一个死锁的例子 java 一个死锁的例子 java 一个死锁的例子
Java多线程程序死锁检查 JCarder
生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,如下图所示,生产者向空间里存放数据,而消费者取用数据,如果不加以协调可能会出现以下情况: 生产者消费者...
《生产者与消费者问题算法实现》 设计思想 因为有多个缓冲区,所以生产者线程没有必要在生成新的数据之前等待最后一个数据被消费者线程处理完毕。同样,消费者线程并不一定每次只能处理一个数据。在多缓冲区机制下...
java线程实践,了解线程死锁,同步问题
Java解决死锁问题eclipse代码版
死锁详解,详细的为你讲解什么事死锁,如何克服死锁。
主要介绍了java中常见的死锁以及解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
死锁问题是个写代码过程中可能遇到的问题,这是我学习中看到的例子
什么情况下Java程序会产生死锁?如何定位、修复?pdf中有介绍
java多线程死锁预防机制研究,java多线程死锁预防机制研究