Java util concurrent及基本线程原理简介

一:什么是JUC

JUC就是java.util.concurrent下面的类包,专门用于多线程的开发。

二:进程和线程的区别

进程是可并发执行的程序在某个数据集合上的一次计算活动,也是操作系统进行资源分配和调度的基本单位。

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与 同属一个进程的其他的线程共享进程所拥有的全部资源。

并发:多线程、 多个线程操作一个资源类,快速交替过程。

并行:多核多CPU;

线程的状态:(java底层源码)

 public enum State {
    NEW,         // 新建线程
    RUNNABLE,    // 线程运行
    BLOCKED,     // 线程阻塞
   WAITING, // 等待
   TIMED_WAITING, // 延时等待
   TERMINATED; // 线程销毁
}

三:wait和sleep的区别

1:类层面

wait ------object

sleep-------Thread 谁调用谁睡觉

2:是否释放锁层面

wait --------释放锁

sleep--------不释放锁

3:使用范围层面

wait,notify,notifyall只能在同步方法中或者同步代码块中使用

sleep可以再任意的地方使用

4:异常

sleep必须捕获异常

wait不需要捕获异常

四:线程的几种使用方式

1.优先级

public final void setPriority(int newPriority)

更改线程的优先级。

默认为5,最小为1,最大为10

设置了优先级别之后,级别高 并不是说你一定被优先调度,而是你的被优先调度的概率高而已。

public class Test {
  public static void main(String[] args) {

    Tuzi tz=new Tuzi("兔子");
    tz.setPriority(2);
    tz.start();

    Wugui wg=new Wugui("乌龟");
    wg.setPriority(8);
    wg.start();
  }
}

public class Wugui extends Thread {
  @Override
  public void run() {
    for (int i = 1; i <=100; i++) {
      System.out.println("我是乌龟我在跑。。"+"----"+this.getName()+"---"+this.getPriority());
    }
  }
  public Wugui(String name) {
    super(name);
  }
}

2.线程强制运行:join()

可以通过join()方法使得一个线程强制运行,线程强制运行期间,其他线程无法运行,必须等待此线程完成之后,才可以继续运行。

public final void join() throws InterruptedException

等待该线程终止。

public final void join(long millis)throws InterruptedException

等待该线程终止的时间最长为 millis 毫秒。超时为 0 意味着要一直等下去。

package Thread1;
class MyThread implements Runnable{  // 实现Runnable接口
  public void run(){  // 覆写run()方法
    for(int i=0;i<50;i++){
      System.out.println(Thread.currentThread().getName()
          + "运行,i = " + i) ;  // 取得当前线程的名字
    }
  }
};
public class demo1{
  public static void main(String args[]){
    MyThread mt = new MyThread() ;  // 实例化Runnable子类对象
    Thread t = new Thread(mt,"线程");    // 实例化Thread对象
    t.start() ;  // 启动线程
    for(int i=0;i<50;i++){
      if(i>10){
        try{
          t.join() ;  // 线程强制运行
        }catch(InterruptedException e){}
      }
      System.out.println("Main线程运行 --> " + i) ;
    }
  }
};

3 线程的休眠(sleep)

  在线程中允许一个线程进行暂时的休眠,直接使用Thread.sleep()方法即可。

  sleep定义格式:

public static void sleep(long milis,int nanos)
throws InterruptedException

  首先,static,说明可以由Thread类名称调用,其次throws表示如果有异常要在调用此方法处处理异常。

所以sleep()方法要有InterruptedException 异常处理,而且sleep()调用方法通常为Thread.sleep(500) ;形式。

控制当前线程休眠若干毫秒

* 1秒= 1000毫秒

* 1秒 = 1000 * 1000 * 1000纳秒 1000000000

package Thread1;
class MyThread implements Runnable{  // 实现Runnable接口
  public void run(){  // 覆写run()方法
    for(int i=0;i<50;i++){
      try{
          Thread.sleep(500) ;  // 线程休眠
      }catch(InterruptedException e){}
      System.out.println(Thread.currentThread().getName()
          + "运行,i = " + i) ;  // 取得当前线程的名字
    }
  }
};
public class demo1{
  public static void main(String args[]){
    MyThread mt = new MyThread() ;  // 实例化Runnable子类对象
    Thread t = new Thread(mt,"线程");    // 实例化Thread对象
    t.start() ;  // 启动线程
  }
};

4.线程的礼让(yield)

yield()方法实现线程的礼让。

package Thread1;
class MyThread implements Runnable{  // 实现Runnable接口
  public void run(){  // 覆写run()方法
    for(int i=0;i<5;i++){
      try{
        Thread.sleep(500) ;  //休眠一下
      }catch(Exception e){}
      System.out.println(Thread.currentThread().getName()
          + "运行,i = " + i) ;  // 取得当前线程的名字
      if(i==2){
        System.out.print("线程礼让:") ;
        Thread.currentThread().yield() ;  // 首先获取当前线程,然后线程礼让
      }
    }
  }
};
public class demo1{
  public static void main(String args[]){
    MyThread my = new MyThread() ;  // 实例化MyThread对象
    Thread t1 = new Thread(my,"线程A") ;
    Thread t2 = new Thread(my,"线程B") ;
    t1.start() ;
    t2.start() ;
  }
};

5.判断线程是否在执行:isAlive

class MyThread implements Runnable{  // 实现Runnable接口
  public void run(){  // 覆写run()方法
    for(int i=0;i<3;i++){
      System.out.println(Thread.currentThread().getName()
          + "运行,i = " + i) ;  // 取得当前线程的名字
    }
  }
};
public class ThreadAliveDemo{
  public static void main(String args[]){
    MyThread mt = new MyThread() ;  // 实例化Runnable子类对象
    Thread t = new Thread(mt,"线程");    // 实例化Thread对象
    System.out.println("线程开始执行之前 --> " + t.isAlive()) ;   // 判断是否启动
    t.start() ;  // 启动线程
    System.out.println("线程开始执行之后 --> " + t.isAlive()) ;   // 判断是否启动
    for(int i=0;i<3;i++){
      System.out.println(" main运行 --> " + i) ;
    }
    // 以下的输出结果不确定
    System.out.println("代码执行之后 --> " + t.isAlive()) ;   // 判断是否启动

  }
};

6.当前线程:CurrentThread()

  程序可以通过currentThread()方法取得当前正在运行的线程对象,

class MyThread implements Runnable{  // 实现Runnable接口
  public void run(){  // 覆写run()方法
    for(int i=0;i<3;i++){
      System.out.println(Thread.currentThread().getName()
          + "运行,i = " + i) ;  // 取得当前线程的名字
    }
  }
};
public class CurrentThreadDemo{
  public static void main(String args[]){
    MyThread mt = new MyThread() ;  // 实例化Runnable子类对象
    new Thread(mt,"线程").start() ;    // 启动线程
    mt.run() ;  // 直接调用run()方法
  }
};

7.线程名称

  1,在Thread类中可以通过getName()方法取得线程名称,通过setName()设置线程名称。

  2,线程的名称一般在启动线程前设置,但也允许为运行的线程设置名称,允许两个Thread对象有相同名称,但是应该避免。

  3,如果程序没有为线程指定名称,系统会自动为线程设置名称。

class MyThread implements Runnable{  // 实现Runnable接口
  public void run(){  // 覆写run()方法
    for(int i=0;i<3;i++){
      System.out.println(Thread.currentThread().getName()
          + "运行,i = " + i) ;  // 取得当前线程的名字
    }
  }
};
public class ThreadNameDemo{
  public static void main(String args[]){
    MyThread mt = new MyThread() ;  // 实例化Runnable子类对象
    new Thread(mt).start() ;    // 系统自动设置线程名称
    new Thread(mt,"线程-A").start() ;    // 手工设置线程名称
    new Thread(mt,"线程-B").start() ;    // 手工设置线程名称
    new Thread(mt).start() ;    // 系统自动设置线程名称
    new Thread(mt).start() ;    // 系统自动设置线程名称
  }
};

五:几种方法的比较

  • Thread.sleep(long millis),一定是当前线程调用此方法,当前线程进入阻塞,但不释放对象锁,millis后线程自动苏醒进入可运行状态。作用:给其它线程执行机会的最佳方式。
  • Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的cpu时间片,由运行状态变会可运行状态,让OS再次选择线程。作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。
  • t.join()/t.join(long millis),当前线程里调用其它线程1的join方法,当前线程阻塞,但不释放对象锁,直到线程1执行完毕或者millis时间到,当前线程进入可运行状态。
  • obj.wait(),当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout)timeout时间到自动唤醒。
  • obj.notify()唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java操作XML工具类XmlUtil详解

    本文实例为大家分享了Java操作XML工具类的具体代码,供大家参考,具体内容如下 一.代码 public class XmlUtil { /** * 将XML文件输出到指定的路径 * * @param doc * @param fileName * @throws Exception */ public static void outputXml(Document doc, String fileName) throws Exception { TransformerFactory tf = T

  • java拓展集合工具类CollectionUtils

    拓展集合工具类CollectionUtils,供大家参考,具体内容如下 package com.demo.utils; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.uti

  • tomcat启动报错:java.util.zip.ZipException的解决方法

    发现问题 早上起来报错误,Jenkins打包到tomcat服务器,死活启动不起来,一些定时任务也没跑成功. 报错如下: org.apache.catalina.startup.ContextConfig.beforeStart Exception fixing docBase for context [/test] java.util.zip.ZipException: error in opening zip file at java.util.zip.ZipFile.open(Native

  • Java StringUtils字符串分割转数组的实现

    我们在日常开发时会经常遇到将一个字符串按照指定的字符进行分割. 这时,我们往往会想到使用str.split(","),进行处理得到分割后的数组. 然而, 使用split()方法在分割特殊的字符时是需要转移的.如小数点"." 下面我为大家推荐一种可以无需转义,即可分割的方法. 使用 org.springframework.util.StringUtils 中的 delimitedListToStringArray(str,delimiter) 进行测试 public

  • Java实现的JSONUtil工具类与用法示例

    本文实例讲述了Java实现的JSONUtil工具类与用法.分享给大家供大家参考,具体如下: import java.util.HashMap; import java.util.Map; import com.alibaba.druid.util.StringUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; public class JSONUtils { /** * Bean对象转J

  • Java中StringUtils工具类进行String为空的判断解析

    判断某字符串是否为空,为空的标准是str==null或str.length()==0 1.下面是StringUtils判断是否为空的示例: StringUtils.isEmpty(null) = true StringUtils.isEmpty("") = true StringUtils.isEmpty(" ") = false //注意在 StringUtils 中空格作非空处理 StringUtils.isEmpty(" ") = fals

  • Java util concurrent及基本线程原理简介

    一:什么是JUC JUC就是java.util.concurrent下面的类包,专门用于多线程的开发. 二:进程和线程的区别 进程是可并发执行的程序在某个数据集合上的一次计算活动,也是操作系统进行资源分配和调度的基本单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与 同属一个进程的其他的线程共享进程所拥有的全部资源. 并发:多线程. 多个线程操

  • 浅谈java.util.concurrent包中的线程池和消息队列

    1.java并发包介绍 JDK5.0(JDK1.5更名后)以后的版本引入高级并发特性,大多数的特性在java.util.concurrent包中,是专门用于多线程编程的,充分利用了现代多处理器和多核心系统的功能以编写大规模并发应用程序.主要包括原子量.并发集合.同步器.可重入锁,并对线程池的构造提供了强力的支持 2.线程池 java.util.concurrent.Executors提供了一个 java.util.concurrent.Executor接口的实现用于创建线程池 多线程技术主要解决

  • Java中JUC包(java.util.concurrent)下的常用子类

    目录 一.对象锁juc.locks包 二.原子类 三.四个常用工具类 3.1 信号量 Semaphore 3.2 CountDownLatch 总结 一.对象锁juc.locks包 在Java中除了synchronized关键字可以实现对象锁之外,java.util.concurrent中的Lock接口也可以实现对象锁. 介绍一下这个lock锁的简要实现: JDK1.0就有的,需要JVM借助操作系统提供的mutex系统原语实现 JDK1.5之后,Java语言自己实现的互斥锁实现,不需要借助操作系

  • java.util.concurrent.ExecutionException 问题解决方法

    java.util.concurrent.ExecutionException错误信息,这里给出解决方案,大家根据具体要求更改. SEVERE: A child container failed during start java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].Standa

  • 深入Synchronized和java.util.concurrent.locks.Lock的区别详解

    主要相同点:Lock能完成Synchronized所实现的所有功能.主要不同点:Lock有比Synchronized更精确的线程予以和更好的性能.Synchronized会自动释放锁,但是Lock一定要求程序员手工释放,并且必须在finally从句中释放.synchronized 修饰方法时 表示同一个对象在不同的线程中 表现为同步队列如果实例化不同的对象 那么synchronized就不会出现同步效果了.1.对象的锁 所有对象都自动含有单一的锁. JVM负责跟踪对象被加锁的次数.如果一个对象被

  • 浅谈Java中的atomic包实现原理及应用

    1.同步问题的提出 假设我们使用一个双核处理器执行A和B两个线程,核1执行A线程,而核2执行B线程,这两个线程现在都要对名为obj的对象的成员变量i进行加1操作,假设i的初始值为0,理论上两个线程运行后i的值应该变成2,但实际上很有可能结果为1. 我们现在来分析原因,这里为了分析的简单,我们不考虑缓存的情况,实际上有缓存会使结果为1的可能性增大.A线程将内存中的变量i读取到核1算数运算单元中,然后进行加1操作,再将这个计算结果写回到内存中,因为上述操作不是原子操作,只要B线程在A线程将i增加1的

  • 详解Java阻塞队列(BlockingQueue)的实现原理

    阻塞队列 (BlockingQueue)是Java util.concurrent包下重要的数据结构,BlockingQueue提供了线程安全的队列访问方式:当阻塞队列进行插入数据时,如果队列已满,线程将会阻塞等待直到队列非满:从阻塞队列取数据时,如果队列已空,线程将会阻塞等待直到队列非空.并发包下很多高级同步类的实现都是基于BlockingQueue实现的. BlockingQueue 的操作方法 BlockingQueue 具有 4 组不同的方法用于插入.移除以及对队列中的元素进行检查.如果

  • 剖析Java中阻塞队列的实现原理及应用场景

    我们平时使用的一些常见队列都是非阻塞队列,比如PriorityQueue.LinkedList(LinkedList是双向链表,它实现了Dequeue接口). 使用非阻塞队列的时候有一个很大问题就是:它不会对当前线程产生阻塞,那么在面对类似消费者-生产者的模型时,就必须额外地实现同步策略以及线程间唤醒策略,这个实现起来就非常麻烦.但是有了阻塞队列就不一样了,它会对当前线程产生阻塞,比如一个线程从一个空的阻塞队列中取元素,此时线程会被阻塞直到阻塞队列中有了元素.当队列中有元素后,被阻塞的线程会自动

  • java并发等待条件的实现原理详解

    前言 前面介绍了排它锁,共享锁的实现机制,本篇继续学习AQS中的另外一个内容-Condition.想必学过java的都知道Object.wait和Object.notify,同时也应该知晓这两个方法的使用离不开synchronized关键字.synchronized是jvm级别提供的同步原语,它的实现机制隐藏在jvm实现中.作为Lock系列功能中的Condition,就是用来实现类似 Object.wait和Object.notify 对应功能的. 使用场景 为了更好的理解Lock和Condit

  • java并发编程JUC CountDownLatch线程同步

    目录 java并发编程JUC CountDownLatch线程同步 1.CountDownLatch是什么? 2.CountDownLatch 如何工作 3.CountDownLatch 代码例子 java并发编程JUC CountDownLatch线程同步 CountDownLatch是一种线程同步辅助工具,它允许一个或多个线程等待其他线程正在执行的一组操作完成.CountDownLatch的概念在java并发编程中非常常见,面试也会经常被问到,所以一定要好好理解掌握. CountDownLa

随机推荐