java必学必会之线程(2)

 更新时间:2015年12月03日 11:33:31   作者:孤傲苍狼  
本文对java线程进行深入学习,重点介绍了线程同步问题、线程死锁问题,感兴趣的小伙伴们可以参考一下

一、线程的优先级别

  

线程优先级别的使用范例:

package cn.galc.test;

public class TestThread6 {
 public static void main(String args[]) {
 MyThread4 t4 = new MyThread4();
 MyThread5 t5 = new MyThread5();
 Thread t1 = new Thread(t4);
 Thread t2 = new Thread(t5);
 t1.setPriority(Thread.NORM_PRIORITY + 3);// 使用setPriority()方法设置线程的优先级别,这里把t1线程的优先级别进行设置
 /*
  * 把线程t1的优先级(priority)在正常优先级(NORM_PRIORITY)的基础上再提高3级 
  * 这样t1的执行一次的时间就会比t2的多很多     
  * 默认情况下NORM_PRIORITY的值为5
  */
 t1.start();
 t2.start();
 System.out.println("t1线程的优先级是:" + t1.getPriority());
 // 使用getPriority()方法取得线程的优先级别,打印出t1的优先级别为8
 }
}

class MyThread4 implements Runnable {
 public void run() {
 for (int i = 0; i <= 1000; i++) {
  System.out.println("T1:" + i);
 }
 }
}

class MyThread5 implements Runnable {
 public void run() {
 for (int i = 0; i <= 1000; i++) {
  System.out.println("===============T2:" + i);
 }
 }
}
  run()方法一结束,线程也就结束了。

二、线程同步

  

synchronized关键字的使用范例:

package cn.galc.test;

public class TestSync implements Runnable {
 Timer timer = new Timer();

 public static void main(String args[]) {
 TestSync test = new TestSync();
 Thread t1 = new Thread(test);
 Thread t2 = new Thread(test);
 t1.setName("t1");// 设置t1线程的名字
 t2.setName("t2");// 设置t2线程的名字
 t1.start();
 t2.start();
 }

 public void run() {
 timer.add(Thread.currentThread().getName());
 }
}

class Timer {
 private static int num = 0;

 public/* synchronized */void add(String name) {// 在声明方法时加入synchronized时表示在执行这个方法的过程之中当前对象被锁定
 synchronized (this) {
  /*
  * 使用synchronized(this)来锁定当前对象,这样就不会再出现两个不同的线程同时访问同一个对象资源的问题了 只有当一个线程访问结束后才会轮到下一个线程来访问
  */
  num++;
  try {
  Thread.sleep(1);
  } catch (InterruptedException e) {
  e.printStackTrace();
  }
  System.out.println(name + ":你是第" + num + "个使用timer的线程");
 }
 }
}

线程死锁的问题:

package cn.galc.test;

/*这个小程序模拟的是线程死锁的问题*/
public class TestDeadLock implements Runnable {
 public int flag = 1;
 static Object o1 = new Object(), o2 = new Object();

 public void run() {
 System.out.println(Thread.currentThread().getName() + "的flag=" + flag);
 /*
  * 运行程序后发现程序执行到这里打印出flag以后就再也不往下执行后面的if语句了 
  * 程序也就死在了这里,既不往下执行也不退出
  */

 /* 这是flag=1这个线程 */
 if (flag == 1) {
  synchronized (o1) {
  /* 使用synchronized关键字把对象01锁定了 */
  try {
   Thread.sleep(500);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  synchronized (o2) {
   /*
   * 前面已经锁住了对象o1,只要再能锁住o2,那么就能执行打印出1的操作了 
   * 可是这里无法锁定对象o2,因为在另外一个flag=0这个线程里面已经把对象o1给锁住了 
   * 尽管锁住o2这个对象的线程会每隔500毫秒睡眠一次,可是在睡眠的时候仍然是锁住o2不放的
   */
   System.out.println("1");
  }
  }
 }
 /*
  * 这里的两个if语句都将无法执行,因为已经造成了线程死锁的问题 
  * flag=1这个线程在等待flag=0这个线程把对象o2的锁解开, 
  * 而flag=0这个线程也在等待flag=1这个线程把对象o1的锁解开 
  * 然而这两个线程都不愿意解开锁住的对象,所以就造成了线程死锁的问题
  */

 /* 这是flag=0这个线程 */
 if (flag == 0) {
  synchronized (o2) {
  /* 这里先使用synchronized锁住对象o2 */
  try {
   Thread.sleep(500);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  synchronized (o1) {
   /*
   * 前面已经锁住了对象o2,只要再能锁住o1,那么就能执行打印出0的操作了 可是这里无法锁定对象o1,因为在另外一个flag=1这个线程里面已经把对象o1给锁住了 尽管锁住o1这个对象的线程会每隔500毫秒睡眠一次,可是在睡眠的时候仍然是锁住o1不放的
   */
   System.out.println("0");
  }
  }
 }
 }

 public static void main(String args[]) {
 TestDeadLock td1 = new TestDeadLock();
 TestDeadLock td2 = new TestDeadLock();
 td1.flag = 1;
 td2.flag = 0;
 Thread t1 = new Thread(td1);
 Thread t2 = new Thread(td2);
 t1.setName("线程td1");
 t2.setName("线程td2");
 t1.start();
 t2.start();
 }
}

  解决线程死锁的问题最好只锁定一个对象,不要同时锁定两个对象

生产者消费者问题:

package cn.galc.test;

/* 范例名称:生产者--消费者问题
 * 源文件名称:ProducerConsumer.java
 * 要 点:
 * 1. 共享数据的不一致性/临界资源的保护
 * 2. Java对象锁的概念
 * 3. synchronized关键字/wait()及notify()方法
 */

public class ProducerConsumer {
 public static void main(String args[]){
  SyncStack stack = new SyncStack();
  Runnable p=new Producer(stack);
  Runnable c = new Consumer(stack);
  Thread p1 = new Thread(p);
  Thread c1 = new Thread(c);
  
  p1.start();
  c1.start();
 }
}


class SyncStack{ //支持多线程同步操作的堆栈的实现
 private int index = 0;
 private char []data = new char[6]; 
 public synchronized void push(char c){
 if(index == data.length){
 try{
  this.wait();
 }catch(InterruptedException e){}
 }
 this.notify();
 data[index] = c;
 index++;
 }
 public synchronized char pop(){
 if(index ==0){
  try{
  this.wait();
  }catch(InterruptedException e){}
 }
 this.notify();
 index--;
 return data[index];
 }
}


class Producer implements Runnable{
 SyncStack stack; 
 public Producer(SyncStack s){
 stack = s;
 }
 public void run(){
 for(int i=0; i<20; i++){
  char c =(char)(Math.random()*26+'A');
  stack.push(c);
  System.out.println("produced:"+c);
  try{     
  Thread.sleep((int)(Math.random()*1000)); 
  }catch(InterruptedException e){
  }
 }
 }
}


class Consumer implements Runnable{
 SyncStack stack; 
 public Consumer(SyncStack s){
 stack = s;
 }
 public void run(){
 for(int i=0;i<20;i++){
  char c = stack.pop();
  System.out.println("消费:"+c);
  try{     
  Thread.sleep((int)(Math.random()*1000));
  }catch(InterruptedException e){
  }
 }
 }
}

以上就是关于java线程的全部内容介绍,大家可以结合第一篇《java必学必会之线程(1)》进行学习,希望可以帮助到大家。

相关文章

  • Java多线程 volatile关键字详解

    Java多线程 volatile关键字详解

    这篇文章主要介绍了Java多线程 volatile关键字详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • Java解析DICOM图之如何获得16进制数据详解

    Java解析DICOM图之如何获得16进制数据详解

    DICOM就是医学数字成像和通信,是医学图像和相关信息的国际标准(ISO 12052),下面这篇文章主要给大家介绍了关于Java解析DICOM图之如何获得16进制数据的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
    2017-10-10
  • 详解java nio中的select和channel

    详解java nio中的select和channel

    这篇文章主要介绍了java nio中的select和channel
    2019-05-05
  • java设计模式之装饰器模式(Decorator)

    java设计模式之装饰器模式(Decorator)

    这篇文章主要为大家详细介绍了java设计模式之装饰器模式Decorator,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • Spring Boot存在路径遍历漏洞CVE-2021-22118的问题解析

    Spring Boot存在路径遍历漏洞CVE-2021-22118的问题解析

    CVE-2021-22118 是一个在 Spring Boot 中发现的漏洞,该漏洞关系到 Spring Boot 的开发者工具(Devtools)中的远程更新(Remote Update)功能,这篇文章主要介绍了Spring Boot存在路径遍历漏洞CVE-2021-22118,需要的朋友可以参考下
    2023-09-09
  • Java中LinkedList和ArrayList的效率分析

    Java中LinkedList和ArrayList的效率分析

    本文主要介绍了Java中LinkedList和ArrayList的效率分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • spring中实现容器加载完成后再执行自己的方法

    spring中实现容器加载完成后再执行自己的方法

    这篇文章主要介绍了spring中实现容器加载完成后再执行自己的方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • SpringBoot结合Redis实现接口幂等性的示例代码

    SpringBoot结合Redis实现接口幂等性的示例代码

    本文主要介绍了SpringBoot结合Redis实现接口幂等性的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • Spring Data JPA 整合QueryDSL的使用案例

    Spring Data JPA 整合QueryDSL的使用案例

    QueryDSL 是一个用于构建类型安全的 SQL 查询的 Java 库,它的主要目标是简化在 Java 中构建和执行 SQL 查询的过程,同时提供类型安全性和更好的编码体验,对Spring Data JPA 整合QueryDSL使用案例感兴趣的朋友跟随小编一起看看吧
    2023-08-08
  • 使用Spring Data JDBC实现DDD聚合的示例代码

    使用Spring Data JDBC实现DDD聚合的示例代码

    这篇文章主要介绍了使用Spring Data JDBC实现DDD聚合的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09

最新评论