当前位置:文档之家› Java多线程积累

Java多线程积累

Java多线程积累
Java多线程积累

一、多线程并发访问解决方案

synchronized关键字主要解决多线程共享数据同步问题。

ThreadLocal使用场合主要解决多线程中数据因并发产生不一致问题。

ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized 有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。

Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。

当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂。

l java中synchronized用法

使用了synchronized关键字可以轻松地解决多线程共享数据同步问题。

synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,synchronized可作用于instance变量、object reference (对象引用)、static函数和class literals(类名称字面常量)身上。

synchronized取得的锁都是对象;每个对象只有一个锁(lock)与之相关联;实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

synchronized的4种用法

1. 方法声明时使用,线程获得的是成员锁.

2. 对某一代码块使用,synchronized后跟括号,括号里是变量,线程获得的是成员锁. 3.synchronized后面括号里是一对象,此时,线程获得的是对象锁.

4.synchronized后面括号里是类,此时,线程获得的是对象锁.

l https://www.doczj.com/doc/df17088704.html,ng.ThreadLocal()的用法

一、概述

ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。

ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单,在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。

概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。

二、API说明

ThreadLocal()

创建一个线程本地变量。

T get()

返回此线程局部变量的当前线程副本中的值,如果这是线程第一次调用该方法,则创建并初始化此副本。

protected T initialValue()

返回此线程局部变量的当前线程的初始值。最多在每次访问线程来获得每个线程局部变量时调用此方法一次,即线程第一次使用get() 方法访问变量的时候。如果线程先于get 方法调用set(T) 方法,则不会在线程中再调用initialValue 方法。

若该实现只返回null;如果程序员希望将线程局部变量初始化为null 以外的某个值,则必须为ThreadLocal 创建子类,并重写此方法。通常,将使用匿名内部类。initialValue 的典型实现将调用一个适当的构造方法,并返回新构造的对象。

void remove()

移除此线程局部变量的值。这可能有助于减少线程局部变量的存储需求。如果再次访问此线程局部变量,那么在默认情况下它将拥有其initialV alue。

void set(T value)

将此线程局部变量的当前线程副本中的值设置为指定值。许多应用程序不需要这项功能,它们只依赖于initialValue() 方法来设置线程局部变量的值。

在程序中一般都重写initialValue方法,以给定一个特定的初始值。

三、典型实例

四、总结

ThreadLocal使用场合主要解决多线程中数据因并发产生不一致问题。

ThreadLocal为每个线程的中并发访问的数据提供一个副本,通过访问副本来运行业务,这样的结果是耗费了内存,单大大减少了线程同步所带来性能消耗,也减少了线程并发控制的复杂度。

ThreadLocal不能使用原子类型,只能使用Object类型。ThreadLocal的使用比synchronized 要简单得多。

五、ThreadLocal使用的一般步骤

1、在多线程的类(如ThreadDemo类)中,创建一个ThreadLocal对象threadXxx,用来保存线程间需要隔离处理的对象xxx。

2、在ThreadDemo类中,创建一个获取要隔离访问的数据的方法getXxx(),在方法中判断,若ThreadLocal对象为null时候,应该new()一个隔离访问类型的对象,并强制转换为要应用的类型。

3、在ThreadDemo类的run()方法中,通过getXxx()方法获取要操作的数据,这样可以保证每个线程对应一个数据对象,在任何时刻都操作的是这个对象。

二、实现Java 多线程并发控制框架

Java 提供了语言级别的线程支持,所以在 Java 中使用多线程相对于 C,C++ 来说更简单便捷,但本文并不是介绍如何在 Java 中使用多线程来来解决诸如 Web services, Number crunching 或者 I/O processing 之类的问题。在本文中,我们将讨论如何实现一个 Java 多线程的运行框架以及我们是如何来控制线程的并发同步以及顺序执行的。

1、所面临的问题

图 1. 线程场景

这幅图中节点代表一个 single Thread,边代表执行的步骤。

整幅图代表的意思是,ROOT 线程执行完毕后执行 T1 线程,T1 执行完毕后并发的执行 T2 和 T3。而从 T2 和 T3 指向 T4 的两条边表示的是 T4 必须等T2 和 T3 都执行完毕以后才能开始执行。剩下的步骤以此类推,直到 END 作为整个过程的结束。当然,这只是个简略的示意图,可能面对的一个线程场景会有上百个线程。还有,你可以观察到这整个场景只有一个入口点和一个出口点,这意味着什么?在下文中为你解释。

这其中涉及到了 Java 线程的同步互斥机制。例如如何让 T1 在 T2 和 T3 之前运行,如何让 T2 和 T3 都执行完毕之后开启 T4 线程。

2、模型的描述

如何来描述图 1 中所示的场景呢?可以采用 XML 的格式来描述我们的模型。我定义一个“Thread” element 来表示线程。

其中 ID 是线程的唯一标识符,PRETHREAD 便是该线程的直接先决线程的ID,每个线程 ID 之间用逗号隔开。

在 Thread 这个 element 里面可以加入你想要该线程执行任务的具体信息。

实际上模型的描述是解决问题非常重要的一个环节,整个线程场景可以用一种一致的形式来描述,作为 Java 多线程并发控制框架引擎的输入。也就是将线程运行的模式用 XML 来描述出来,这样只用改动 XML 配置文件就可以更改整个线程运行的模式,不用改动任何的源代码。

3、两种实现机制

对于 Java 多线程的运行框架来说,我们将采用“外”和“内”的两种模式来实现。

“外” - 主线程轮询

图 2. 静态类图

Thread 是工作线程。ThreadEntry 是 Thread 的包装类,prerequisite 是一个 HashMap,它含有 Thread 的先决线程的状态。如图1中显示的那样,T4 的先决线程是 T2 和 T3,那么 prerequisite 中就包含 T2 和 T3 的状态。TestScenario 中的 threadEntryList 中包含所有的 ThreadEntry。

图 3. 线程执行场景

TestScenario 作为主线程,作为一个“外”在的监控者,不断地轮询threadEntryList 中所有 ThreadEntry 的状态,当 ThreadEntry 接受到isReady 的查询后查询自己的 prerequisite,当其中所有的先决线程的状态为“正常结束时”,它便返回 ready,那么 TestScenario 便会调用 ThreadEntry 的 startThread() 方法授权该 ThreadEntry 运行线程,Thread 便通过 run() 方法来真正执行线程。并在正常执行完毕后调用 setPreRequisteState() 方法来更新整个 Scenario,threadEntryList 中所有 ThreadEntry 中

prerequisite 里面含有该 Thread 的状态信息为“正常结束”。

图 4. 状态更改的过程

如图 1 中所示的 T4 的先决线程为 T2 和 T3,T2 和 T3 并行执行。如图 4 所示,假设 T2 先执行完毕,它会调用 setPreRequisteState() 方法来更新整个 Scenario, threadEntryList 中所有 ThreadEntry 中 prerequisite 里面含有该 T2 的状态信息为“正常结束”。此时,T4 的 prerequisite 中 T2 的状态为“正常结束”,但是 T3 还没有执行完毕,所以其状态为“未完毕”。所以 T4 的 isReady 查询返回为 false,T4 不会执行。只有当 T3 执行完毕后更新状态为“正常结束”后,T4 的状态才为 ready,T4 才会开始运行。

其余的节点也以此类推,它们正常执行完毕的时候会在整个的 scenario 中广播该线程正常结束的信息,由主线程不断地轮询各个 ThreadEntry 的状态来开启各个线程。

这便是采用主控线程轮询状态表的方式来控制 Java 多线程运行框架的实现方式之一。

优点:概念结构清晰明了,实现简单。避免采用 Java 的锁机制,减少产生死锁的几率。当发生异常导致其中某些线程不能正常执行完毕的时候,不会产生挂起的线程。

缺点:采用主线程轮询机制,耗费 CPU 时间。当图中的节点太多的(n>??? 而线程单个线程执行时间比较短的时候 t

4、“内”- wait?ify

相对于“外”-主线程轮询机制来说,“内”采用的是自我控制连锁触发机制。

图 5. 锁机制的静态类图

Thread 中的 lock 为当前 Thread 的 lock,lockList 是一个 HashMap,持有其后继线程的 lock 的引用,getLock 和 setLock 可以对 lockList 中的Lock 进行操作。其中很重要的一个成员是 waitForCount,这是一个引用计数。表明当前线程正在等待的先决线程的个数,例如图 1 中所示的 T4,在初始的情况下,他等待的先决线程是 T2 和 T3,那么它的 waitForCount 等于 2。

图 6. 锁机制执行顺序图

当整个过程开始运行的时候,我们将所有的线程 start,但是每个线程所持的 lock 都处于 wait 状态,线程都会处于 waiting 的状态。此时,我们将 root thread 所持有的自身的 lock notify,这样 root thread 就会运行起来。当root 的 run 方法执行完毕以后。它会检查其后续线程的 waitForCount,并将其值减一。然后再次检查 waitForCount,如果 waitForCount 等于 0,表示该后续线程的所有先决线程都已经执行完毕,此时我们 notify 该线程的 lock,该后续线程便可以从 waiting 的状态转换成为 running 的状态。然后这个过程连锁递归的进行下去,整个过程便会执行完毕。

我们还是以 T2,T3,T4 为例,当进行 initThreadLock 过程的时候,我们可以知道 T4 有两个直接先决线程 T2 和 T3,所以 T4 的 waitForCount 等于2。我们假设 T3 先执行完毕,T2 仍然在 running 的状态,此时他会首先遍历其所有的直接后继线程,并将他们的 waitForCount 减去 1,此时他只有一个直接后继线程 T4,于是 T4 的 waitForCount 减去 1 以后值变为 1,不等于 0,此时不会将 T4 的 lock notify,T4 继续 waiting。当 T2 执行完毕之后,他会执行与 T3 相同的步骤,此时 T4 的 waitForCount 等于 0,T2 便 notify T4 的 lock,于是 T4 从 waiting 状态转换成为 running 状态。其他的节点也是相似的情况。

当然,我们也可以将整个过程的信息放在另外的一个全局对象中,所有的线程都去查找该全局对象来获取各自所需的信息,而不是采取这种分布式存储的方式。

优点:采用wait?ify 机制而不采用轮询的机制,不会浪费CPU资源。执行效率较高。而且相对于“外”-主线程轮询的机制来说实时性更好。

缺点:采用 Java 线程 Object 的锁机制,实现起来较为复杂。而且采取一种连锁触发的方式,如果其中某些线程异常,会导致所有其后继线程的挂起而造成整个 scenario 的运行失败。为了防止这种情况的发生,我们还必须建立一套线程监控的机制来确保其正常运行。

5、延伸

下面的图所要表达的是这样一种递归迭代的概念。例如在图1 中展示的那样,T1 这个节点表示的是一个线程。现在,忘掉线程这样一个概念,将 T1 抽象为一个过程,想象它是一个银河系,深入到 T1 中去,它也是一个许多子过程的集合,这些子过程之间的关系模式就如图 1 所示那样,可以用一个图来表示。

图 7. 嵌套子过程

可以想象一下这是怎样的一个框架,具有无穷扩展性的过程框架,我们只用定义各个过程之间的关系,我们不用关心过程是怎样运行的。事实上,可以在最终的节点上指定一个实际的工作,比如读一个文件,或者submit一个JCL job,或者执行一条sql statement。

其实,按照某种遍历规则,完全可以将这种嵌套递归的结构转化成为一个一层扁平结构的图,而不是原来的分层的网状结构,但是我们不这样做的原因是基于以下的几点考虑:

如果这样做,会导致图节点太多,边太多,令人眼花缭乱。

不这样做更主要的原因是每一个场景,如图 7 中的 T1,T13,是状态聚集的一个单元,具有高复用性和可靠性。

框架是高度抽象的,它实际的执行可以是分布式的,一个单元可以是一个系统,作为和其他系统的分界标志。

实际上,这是一个状态聚集的层次控制框架,我们可以依赖此框架来执行自主运算。我们将在其它的文章中来讨论它的应用。

6、总结

本文介绍了一种 Java 多线程并发控制的框架,并给出了其两种实现的模型,它们有各自的优缺点,有各自的适用范围。当需要进行 Java 线程的并发控制的时候,可以作为参考

Java多线程技术及案例

Java多线程技术及案例 进程和线程: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1–n个线程。 线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。 线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。 多进程是指操作系统能同时运行多个任务(程序)。 多线程是指在同一程序中有多个顺序流在执行。 Java中多线程的多种实现方式 Java中有多种多线程实现方法,主要是继承https://www.doczj.com/doc/df17088704.html,ng.Thread类的方法和 https://www.doczj.com/doc/df17088704.html,ng.Runnable接口的方法。 继承Thread类 Thread是https://www.doczj.com/doc/df17088704.html,ng包中的一个类,从这个类中实例化的对象代表线程,启动一个新线程需要建立一个Thread实例。 使用Thread类启动新的线程的步骤如下: 1.实例化Thread对象 2.调用start()方法启动线程 构造方法:

public Thread(String threadName); public Thread(); 例程: publicclass Thread1extends Thread{//定义一个类继承Thread privateint count=1000; publicvoid run(){//重写run方法 while(true){ System.out.print(count+" "); if(--count==0){ return; } } } publicstaticvoid main(String[] args){ Thread1 th1=new Thread1();//实例化继承了Thread的类 Thread1 th2=new Thread1(); th1.start();//调用start()方法, th2.start(); for(int i=0;i<1000;i++){ System.out.print("A "); } }

Java多线程和输入输出流

班级:13科技2班学号:201324131225 姓名:许耿宁 Java多线程和输入输出流 一、实验目的: 1.熟悉利用Thread类建立多线程方法。 2.熟悉利用Thread接口建立多线程方法。 3.熟悉Java的文件读写机制,练习输入输出流的使用。 二、实验内容: 1.阅读下列程序,分析并上机检验其功能。 public class DelayRunnable implements Runnable{ private static int count=0; private int no; private int delay; public DelayRunnable(){ count++; no=count; } public void run(){ try{ for (int i=0;i<10;i++){ delay=(int)(Math.random()*5000); Thread.sleep(delay); System.out.println("Thread "+no+" with a delay "+delay); } }catch(InterruptedException e){} } } class MyRunnable{ public static void main(String args[]){ DelayRunnable r1 = new DelayRunnable();

DelayRunnable r2 = new DelayRunnable(); Thread thread1=new Thread(r1); Thread thread2=new Thread(r2); thread1.start(); thread2.start(); try{ Thread.sleep(1000); }catch(InterruptedException e){ System.out.println("Thread wrong"); } } } 2.将上列程序利用Runnable接口改写,并上机检验。 3.创建简单的程序ThreeThread.java,该程序将创建三个线程,每个线程应当显示它所运行的时间(可以考虑使用Date类或Calendar类)。 4.键盘输入10个整数,从小到大进行排序。 5.接收键盘输入的字符串,用FileInputStream类将字符串写入文件,用 FileOutputStream类读出文件内容显示在屏幕上。 6.将一个文本文件的内容按行读出,每读出一行就顺序加上行号,并写入到另一个文件中。 三、实验要求: 1.通过实验掌握Thread 、Runnable使用方法; 2.程序必须能够实现多线程; 3.程序必须能够完成题目要求; 4.通过实验掌握文件输入输出流的使用方法; 5.程序必须能够从键盘接收字符串并保存在文件中; 6.程序必须能够读出文件内容显示在屏幕上; 7.写出实验报告。 四、实验代码及截图: 第一题: 在编译器上运行程序得到截图所示结果:

JAVA多线程试题 答案

多线程 一.选择题 1.下列说法中错误的一项是(A) A.线程就是程序 B.线程是一个程序的单个执行流 B.多线程是指一个程序的多个执行流D.多线程用于实现并发 2.下列哪个一个操作不能使线程从等待阻塞状态进入对象阻塞状态(D) A.等待阴塞状态下的线程被notify()唤 B.等待阻塞状态下的纯种被interrput()中断 C.等待时间到 D.等待阻塞状态下的线程调用wait()方法 3.下列哪个方法可以使线程从运行状态进入其他阻塞状态(A) A.sleep B.wait C.yield D.start 4.下列说法中错误的一项是(D) A.一个线程是一个Thread类的实例 B.线程从传递给纯种的Runnable实例run()方法开始执行 C.线程操作的数据来自Runnable实例 D.新建的线程调用start()方法就能立即进入运行状态 5.下列关于Thread类提供的线程控制方法的说法中,错误的一项是(D) A.在线程A中执行线程B的join()方法,则线程A等待直到B执行完成 B.线程A通过调用interrupt()方法来中断其阻塞状态 C.若线程A调用方法isAlive()返回值为true,则说明A正在执行中 D.currentThread()方法返回当前线程的引用 6.下列说法中,错误的一项是() A.对象锁在synchronized()语句执行完之后由持有它的线程返还 B.对象锁在synchronized()语句中出现异常时由持有它的线程返还 C.当持有锁的线程调用了该对象的wait()方法时,线程将释放其持有的锁 D.当持有锁的线程调用了该对象的构造方法时,线程将释放其持有的锁 7.下面的哪一个关键字通常用来对对象的加锁,从而使得对对象的访问是排他的A A.sirialize B transient C synchronized D static 二.填空题 1.在操作系统中,被称做轻型的进程是线程 2.多线程程序设计的含义是可以将一个程序任务分成几个并行的任务 3.在Java程序中,run()方法的实现有两种方式:实现Runnable接口和继承Thread类 4.多个线程并发执行时,各个线程中语句的执行顺序是确定的,但是线程之间的相对执行顺序是不确定的 6.Java中的对象锁是一种独占的排他锁 7.程序中可能出现一种情况:多个线种互相等待对方持有的锁,而在得到对方的锁之前都不会释放自己的锁,这就是死锁 8.线程的优先级是在Thread类的常数MIN_PRIORITY和MAX_PRIORITY 之间的一个值 9.处于新建状态的线程可以使用的控制方法是start()和stop()。 10.一个进程可以包含多个线程

JAVA线程程序设计(小时钟)实验报告(附完整代码)

线程程序设计 一、课题内容和要求 内容:设计和编写一个编写一个指针式时钟程序,应用线程实现时钟的走动。 要求:本实验旨在通过实验,培养学生将JAVA 线程的相关知识点(包括线程调度,线程同步等)有机结合并加以综合应用,在实验中设计多线程程序的能力。 二、设计思路分析 class Clock:一个指针式时钟的主类 class Layout: 添加窗口和时钟组件 class ClockPaint:定义时钟组件 三、概要设计 public class Clock extends JFrame { public static void main(String[] s) ; } class Layout extends JFrame { public Layout(); } class ClockPaint extends JPanel implements Runnable { int x, y, r; int h, m, s; double rad = Math.PI / 180; public ClockPaint(int x, int y, int r); public void paint(Graphics g); public void run(); } 时钟的绘制:

运行时钟: 四、详细设计 import java.awt.*; import javax.swing.*; import java.util.*; public class Clock extends JFrame { public static void main(String[] s) { new Layout(); } } class Layout extends JFrame {// 添加窗口和时钟组件public Layout() { ClockPaint cp = new ClockPaint(20, 20, 70); add(cp);

15个Java多线程面试题及答案

15个Java多线程面试题及答案 1)现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行? 这个线程问题通常会在第一轮或电话面试阶段被问到,目的是检测你对”join”方法是否熟悉。这个多线程问题比较简单,可以用join方法实现。 2)在Java中Lock接口比synchronized块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,以此来保持它的完整性,你会怎样去实现它? lock接口在多线程和并发编程中最大的优势是它们为读和写分别提 供了锁,它能满足你写像ConcurrentHashMap这样的高性能数据结构和有条件的阻塞。Java线程面试的问题越来越会根据面试者的回答来提问。芯学苑老师强烈建议在你在面试之前认真读一下Locks,因为当前其大量用于构建电子交易终统的客户端缓存和交易连接空间。 3)在java中wait和sleep方法的不同?

通常会在电话面试中经常被问到的Java线程面试问题。最大的不同是在等待时wait会释放锁,而sleep一直持有锁。Wait通常被用于线程间交互,sleep通常被用于暂停执行。 4)用Java实现阻塞队列。 这是一个相对艰难的多线程面试问题,它能达到很多的目的。第一,它可以检测侯选者是否能实际的用Java线程写程序;第二,可以检测侯选者对并发场景的理解,并且你可以根据这个问很多问题。如果他用wait()和notify()方法来实现阻塞队列,你可以要求他用最新的Java 5中的并发类来再写一次。 5)用Java写代码来解决生产者——消费者问题。 与上面的问题很类似,但这个问题更经典,有些时候面试都会问下面的问题。在Java中怎么解决生产者——消费者问题,当然有很多解决方法,我已经分享了一种用阻塞队列实现的方法。有些时候他们甚至会问怎么实现哲学家进餐问题。 6)用Java编程一个会导致死锁的程序,你将怎么解决?

java多线程并发面试题【java多线程和并发基础面试题】

java多线程并发面试题【java多线程和并 发基础面试题】 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一。下面就由小编为大家介绍一下java多线程和并发基础面试题的文章,欢迎阅读。 java多线程和并发基础面试题篇1 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一个包含了不同的类和程序的单一进程。线程可以被称为轻量级进程。线程需要较少的来创建和驻留在进程中,并且可以共享进程中的。 2. 多线程编程的好处是什么? 在多线程程序中,多个线程被并发的执行以提高程序的效率,CPU不会因为某个线程需要等待而进入空闲状态。多个线程共享堆内存(heap memory),因此创建多个线程去执行一些任务会比创建多个进程更好。举个例子,Servlets比CGI更好,是因为Servlets支持多线程而CGI不支持。 3. 用户线程和守护线程有什么区别? 当我们在Java程序中创建一个线程,它就被称为用户线程。一个守护线程是在后台执行并且不会阻止JVM终止的

线程。当没有用户线程在运行的时候,JVM关闭程序并且退出。一个守护线程创建的子线程依然是守护线程。 4. 我们如何创建一个线程? 有两种创建线程的方法:一是实现Runnable接口,然后将它传递给Thread的构造函数,创建一个Thread对象;二是直接继承Thread类。 java多线程和并发基础面试题篇2 1. 有哪些不同的线程生命周期? 当我们在Java程序中新建一个线程时,它的状态是New。当我们调用线程的start()方法时,状态被改变为Runnable。线程调度器会为Runnable线程池中的线程分配CPU时间并且讲它们的状态改变为Running。其他的线程状态还有Waiting,Blocked 和Dead。 2. 可以直接调用Thread类的run()方法么? 当然可以,但是如果我们调用了Thread的run()方法,它的行为就会和普通的方法一样,为了在新的线程中执行我们的代码,必须使用Thread.start()方法。 3. 如何让正在运行的线程暂停一段时间? 我们可以使用Thread类的Sleep()方法让线程暂停一段时间。需要注意的是,这并不会让线程终止,一旦从休眠中唤醒线程,线程的状态将会被改变为Runnable,并且根据线程调度,它将得到执行。

java线程学习总结

java线程学习总结1(java thread培训总结1) 1.线程中一些基本术语和概念 (2) 1.1线程的几个状态 (2) 1.2 Daemon线程 (2) 1.3锁的定义 (2) 1.4死锁 (2) 1.5.Java对象关于锁的几个方法 (3) 1.6锁对象(实例方法的锁) (3) 1.7类锁 (4) 1.8.线程安全方法与线程不安全方法 (4) 1.9类锁和实例锁混合使用 (4) 1.10锁的粒度问题 (4) 1.11.读写锁 (5) 1.12 volatile (5) 2.线程之间的通讯 (5) 2.1屏障 (6) 2.2.锁工具类 (6) 2.3.条件变量 (6) 3. Java线程调度 (7) 3.1 Java优先级 (7) 3.2. 绿色线程 (7) 3.3 本地线程 (7) 3.4 Windows本地线程 (7) 3.5线程优先级倒置与继承 (8) 3.6循环调度 (8) 4.线程池 (8) 5工作队列 (9) 6.参考资料 (10)

1.线程中一些基本术语和概念 1.1线程的几个状态 初始化状态 就绪状态 运行状态 阻塞状态 终止状态 1.2 Daemon线程 Daemon线程区别一般线程之处是:主程序一旦结束,Daemon线程就会结束。 1.3锁的定义 为了协调多个并发运行的线程使用共享资源才引入了锁的概念。 1.4死锁 任何多线程应用程序都有死锁风险。当一组线程中的每一个都在等待一个只 有该组中另一个线程才能引起的事件时,我们就说这组线程死锁了。换一个说法就是一组线程中的每一个成员都在等待别的成员占有的资源时候,就可以说这组线程进入了死锁。死锁的最简单情形是:线程 A 持有对象X 的独占锁,并且在等待对象Y 的锁,而线程 B 持有对象Y 的独占锁,却在等待对象X 的锁。除非有某种方法来打破对锁的等待(Java 锁定不支持这种方法),否则死锁的线程将永远等下去。

多线程总结

最近想将java基础的一些东西都整理整理,写下来,这是对知识的总结,也是一种乐趣。已经拟好了提纲,大概分为这几个主题: java线程安全,java垃圾收集,java并发包详细介绍,java profile和jvm性能调优。慢慢写吧。本人jameswxx原创文章,转载请注明出处,我费了很多心血,多谢了。关于java线程安全,网上有很多资料,我只想从自己的角度总结对这方面的考虑,有时候写东西是很痛苦的,知道一些东西,想用文字说清楚,却不是那么容易。我认为要认识 java线程安全,必须了解两个主要的点:java的内存模型,java的线程同步机制。特别是内存模型,java的线程同步机制很大程度上都是基于内存模型而设定的。从暂时写得比较仓促,后面会慢慢补充完善。 浅谈java内存模型 不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的。java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安全无非要控制多个线程对某个资源的有序访问或修改。java的内存模型,要解决两个主要的问题:可见性和有序性。我们都知道计算机有高速缓存的存在,处理器并不是每次处理数据都是取内存的。JVM定义了自己的内存模型,屏蔽了底层平台内存管理细节,对于java开发人员,要解决的是在jvm内存模型的基础上,如何解决多线程的可见性和有序性。 那么,何谓可见性?多个线程之间是不能互相传递数据通信的,它们之间的沟通只能通过共享变量来进行。Java内存模型(JMM)规定了jvm有主内存,主内存是多个线程共享的。当new一个对象的时候,也是被分配在主内存中,每个线程都有自己的工作内存,工作内存存储了主存的某些对象的副本,当然线程的工作内存大小是有限制的。当线程操作某个对象时,执行顺序如下: (1) 从主存复制变量到当前工作内存 (read and load) (2) 执行代码,改变共享变量值 (use and assign) (3) 用工作内存数据刷新主存相关内容 (store and write) JVM规范定义了线程对主存的操作指令:read,load,use,assign,store,write。当一个共享便变量在多个线程的工作内存中都有副本时,如果一个线程修改了这个共享变量,那么其他线程应该能够看到这个被修改后的值,这就是多线程的可见性问题。 那么,什么是有序性呢?线程在引用变量时不能直接从主内存中引用,如果线程工作内存中没有该变量,则会从主内存中拷贝一个副本到工作内存中,这个过程为read-load,完成后线程会引用该副本。当同一线程再度引用该字段时,有可能重新从主存中获取变量副本(read-load-use),也有可能直接引用原来的副本 (use),也就是说 read,load,use顺序可以由JVM实现系统决定。 线程不能直接为主存中中字段赋值,它会将值指定给工作内存中的变量副本(assign),完成后这个变量副本会同步到主存储区(store- write),至于何时同步过去,根据JVM实现系统决定.有该字段,则会从主内存中将该字段赋值到工作内存中,这个过程为read-load,完成后线程会引用该变量副本,当同一线程多次重复对字段赋值时,比如: for(int i=0;i<10;i++) a++; 线程有可能只对工作内存中的副本进行赋值,只到最后一次赋值后才同步到主存储区,所以assign,store,weite顺序可以由JVM实现系统决定。假设有一个共享变量x,线程a执行x=x+1。从上面的描述中可以知道x=x+1并不是一个原子操作,它的执行过程如下:

Java并发编程实践

1对象的共享 关键字synchronized不仅能实现原子性还能确保当一个线程修改了对象状态后,另一个线程就可以看到对象状态的变化(内存可见性) 1.1可见性 重排序:在缺乏足够同步的多线程程序中,代码的执行顺序不会按照程序员写好的顺序进行。这是因为Java内存模型允许编译器、CPU对操作的执行顺序进行调整。 1.1.1失效数据 在多线程程序中,get方法、set方法都需要进行同步。这是因为get方法在获取变量时可能会获得一个失效的值,这个失效的值就是之前某个线程设置的。虽然已经失效但这个值曾经是正确的。 1.1.2非原子的64位操作 Java内存模型要求,非volatile类型的64位数值变量(double和long),JVM允许将64位的读操作和写操作分解为两个32位的操作。 那么在多线程的环境中,如果要读取非volatile类型的double、隆就有可能会读取到某个值的高32位和另一个值的低32位组成的一个数值。 但目前各种平台的商用虚拟机几乎都把64位数据的读写操作作为原子操作来对待。1.1.3加锁与可见性 加锁的含义不仅仅局限于互斥行为,还包括内存可见性。为了确保所有线程都能看到共享变量的最新值,所有执行读操作或者写操作的线程都必须在同一个锁上同步。 同步代码块的锁就是方法调用所在的对象,静态synchronized方法以Class对象作为锁。 synchronized可以用于实例变量、对象引用、static方法、类名称字面常量。 1.在某个对象实例内,synchronized aMethod(){} 可以防止多个线程同时访问这个对象其他

的synchronized方法(这个对象还有其他的synchronized方法,如果其中一个线程访问了其中一个synchronized方法,那么其他线程将不能访问此对象另外的synchronized方法)。但不同的对象实例间的synchronized方法是相互独立的,也就是说其他线程照样可以访问相同类的另一个对象实例的synchronized方法。 2.synchronized static aMethod(){}对这个类所有的静态synchronized方法都会起作用,但 不会对非静态的synchronized起作用。这是因为static方法属于类方法,他属于这个Class (注意:这里的Class不是指Class的某个具体对象),那么static方法所获取到的锁就是调用这个方法的对象所属的类,而非static方法获取到的锁就是当前调用这个方法的对象了。 3.除了在方法上用synchronized关键字外,也可以在方法内部的某个区块中用synchronized 表示只对这个区块中的资源进行同步访问,例如synchronized(this){/**区块**/}的作用域就是当前对象。 1.1.3.1非static方法 运行结果是:chunk对象与chunk1对象锁互不干扰。 chunk1 9chunk

java学习整体总结

CoreJava部分 1 简述下java基本数据类型及所占位数,java基本数据类型:4类8种 整数类型:byte(1byte),short(2byte),int(4byte),long(8byte) 浮点类型:float(4byte),double(8byte) 字符类型:char(2byte) 逻辑类型:boolean(false/true 1byte) 2 说出5个启动时异常 RunTimeException ------NullPointerException ------ArrayIndexOutOfBoundsException ------ClassCastException ------NumberFormatException 3 HashMap 和HashTable的区别: 1HashMap 允许空键值对,HashTable不允许 2HashMap不是线程安全的,HashTable是 3HashMap直接实现Map接口,HashTable继承Dictionary类 4. ArrayList,Vector,LinkedList存储性能和区别 它们都实现了List接口 ArrayList和Vector都是基于数组实现的 LinkedList基于双向循环链表(查找效率低,添加删除容易) ArrayList不是线程安全的而Vector是线程安全的,所有速度上 ArrayList高于Vector 5. Collection和Collections的区别 Collection是集合类的上级接口,继承与他的接口主要有Set和List Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全等操作。 6 List、Map、Set三个接口,存取元素时,各有什么特点? List以特定次序来持有元素,可有重复元素。 Set 无法持有重复元素,内部排序 Map保存key-value值,value可多值。 7 final,finally,finalize的区别 Final用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承 Finally 是异常处理语句结构的一部分,表示总是执行 Finalize 是Object类的一个方法,在垃圾收集时的其他资源回收,例如关闭文件等。 8 Overload和Override的区别。Overload的方法是否可以改变返回值的

Java多线程详解

JAVA多线程编程详解 一、理解多线程 多线程是这样一种机制,它允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间互相独立。线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享 一个存储空间,这使得线程间的通信远较进程简单。 具体到java内存模型,由于Java 被设计为跨平台的语言,在内存管理上,显然也要有一个统一的模型。系统存在一个主内存(Main Memory),Java 中所有变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。 “”“” 多个线程的执行是并发的,也就是在逻辑上同时,而不管是否是物理上的同时。如 ,那么真正的同时是不可能的。多线程和传统的单线程在程序设计果系统只有一个CPU“” 上最大的区别在于,由于各个线程的控制流彼此独立,使得各个线程之间的代码是乱序执 行的,将会带来线程调度,同步等问题。 二、在Java中实现多线程 我们不妨设想,为了创建一个新的线程,我们需要做些什么?很显然,我们必须指明 这个线程所要执行的代码,而这就是在Java中实现多线程我们所需要做的一切! 作为一个完全面向对象的语言,Java提供了类https://www.doczj.com/doc/df17088704.html,ng.Thread 来方便多线程编程,这个类提供了大量的方法来方便我们控制自己的各个线程。 那么如何提供给Java 我们要线程执行的代码呢?让我们来看一看Thread 类。Thread 类最重要的方法是run(),它为Thread 类的方法start()所调用,提供我们的线程所要执行的代码。为了指定我们自己的代码,只需要覆盖它! 方法一:继承Thread 类,重写方法run(),我们在创建的Thread 类的子类中重写run(),加入线程所要执行的代码即可。下面是一个例子:

java并发编程艺术总结.

1、并发编程的挑战 上下文切换:CPU通过时间片分配算法来循环执行任务,在切换任务的过程中,会保存上一个任务的状态,以便在下次切换回这个任务时,可以再加载这个任务的状态。 减少上下文切换的方法:无锁并发编程、CAS算法、使用最少线程和使用协程 2、Java并发机制的底层实现原理 Java代码编译后java字节码然后加载到JVM然后转化为CUP执行的汇编,java的并发依赖于JVM的实现与CPU的指令。 1. Volatile的应用 可见性:当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。 后面还是详细介绍volatile关键字 2. synchronized的实现原理与应用 1) synchronized简介 synchronized在JVM中实现,JVM基于进入与退出Monitor对象来实现方法同步与代码块同步,在同步代码块前后分别形成monitorenter和monitorexit这两个字节码。synchronized的锁存放在java对象头里,在对象头里有关于锁的信息:轻量级锁,重量级锁,偏向锁。(对象头里还包括:GC标记、分代年龄、线程ID、HashCode等。) 2) 锁的介绍 级别从低到高:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态,锁能升级不能降级,目的是提高获取锁和释放锁的效率。 偏向锁: 在大多数情况下,锁不仅不存在多线程竞争,而且总是由同一个线程多次获得。

为了让线程获得锁的代价更低而引入了偏向锁。 当一个线程访问同步块并获取锁(对象)时,会在对象头里记录偏向锁的线程ID。以后该线程进入与退出同步块时不需要进行CAS操作来加锁和解锁。如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会尝试消除它身上的偏向锁,将锁恢复到标准的轻量级锁。 轻量级锁: 线程通过CAS来获取锁(线程栈帧中有存储锁记录的空间,将Mask Word复制到锁记录中,然后尝试使用CAS将对象头中的Mask Word替换成指向锁记录的指针),如果成功,就获取锁,失败就尝试自旋来获取锁。 重量级锁: 为了避免在轻量级中无用的自旋(比如获取到锁的线程被阻塞住了),JVM可以将锁升级成重量级。当锁处于这个状态时,其他线程试图获取锁时,都会被阻塞住,当持有锁的线程释放锁之后会唤醒这些线程。 锁优点缺点使用场景 偏向锁加锁与解锁不需要 额外的消耗。线程存在竞争时, 会带来额外的锁撤 销的消耗 适用于只有一个 线程访问同步块 轻量级锁竞争的线程不会阻 塞,提高了程序的 响应速度始终得不到锁竞争 的线程,自旋消耗 CPU 追求响应时间, 同步块执行速度 非常快 重量级锁线程竞争不使用自 旋,不会消耗CPU 线程阻塞,响应时 间缓慢 追求吞吐量,同 步块执行时间较 长 3. 原子操作的实现原理 原子:不能被中断的一个或一系列操作。 在java中可以通过锁和循环CAS的方式来实现原子操作。 1) 使用循环CAS实现原子操作 利用处理器提供的CAS指令来实现,自旋CAS现在的基本思路就是循环进

JAVA多线程编程详解-详细操作例子

一、理解多线程 多线程是这样一种机制,它允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间互相独立。线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单。 具体到java内存模型,由于Java被设计为跨平台的语言,在内存管理上,显然也要有一个统一的模型。系统存在一个主内存(Main Memory),Java中所有变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。 多个线程的执行是并发的,也就是在逻辑上“同时”,而不管是否是物理上的“同时”。如果系统只有一个CPU,那么真正的“同时”是不可能的。多线程和传统的单线程在程序设计上最大的区别在于,由于各个线程的控制流彼此独

立,使得各个线程之间的代码是乱序执行的,将会带来线程调度,同步等问题。 二、在Java中实现多线程 我们不妨设想,为了创建一个新的线程,我们需要做些什么?很显然,我们必须指明这个线程所要执行的代码,而这就是在Java中实现多线程我们所需要做的一切! 作为一个完全面向对象的语言,Java提供了类https://www.doczj.com/doc/df17088704.html,ng.Thread 来方便多线程编程,这个类提供了大量的方法来方便我们控制自己的各个线程。 那么如何提供给Java 我们要线程执行的代码呢?让我们来看一看Thread 类。Thread 类最重要的方法是run (),它为Thread 类的方法start()所调用,提供我们的线程所要执行的代码。为了指定我们自己的代码,只需要覆盖它! 方法一:继承Thread 类,重写方法run(),我们在创建Thread 类的子类中重写run(),加入线程所要执行的代码即可。下面是一个例子:

java实现多线程的网络并发服务器

课程设计说明书 课程名称: 操作系统原理-课程设计 课程代码: 题目: 多线程的网络并发服务器设计 年级/专业/班: 学生姓名: 学号: 开始时间:2011 年12月11日 完成时间:2011 年12月24 日 课程设计成绩: 指导教师签名:年月日

目录 1 引言 (1) 1.1问题的提出 (1) 1.2国内外研究的现状 (1) 1.3任务与分析 (1) 2 程序的主要功能 (2) 2.1客户端接收和发送消息功能 (2) 2.2服务器分配和回收序号功能 (2) 2.3服务器显示信息功能 (2) 3 程序运行平台 (3) 4 总体设计 (4) 5 程序类的说明 (5) 6 模块分析 (10) 6.1客服端模块 (10) 6.2服务器模块 (10) 6.3处理客户端线程的模块 (12) 6.4服务器线程模块 (12) 7 系统测试 (13) 8 结论 (18) 参考文献 (19) I

1 引言 1.1 问题的提出 在现代化的生活中,网络无处不在,那么是怎样来实现客户与服务器的通信的呢,服务器是怎样来实现处理不同客户端发来的请求,这就涉及到多线程的网络并发服务器的设计。 1.2国内外研究的现状 传统的并发服务器往往是基于多进程机制的,每个客户一个进程,需要操作系统的干预,进程数目受操作系统的限制。然而许多新型操作系统都是多线程,将并行服务器设计为多线程,可以增加其效率。这样,不必为每个服务请求启动一个单独的进程或任务,多线程并行服务器可以启动一个执行速度更快的独立线程。如果主机是多处理器的,则多线程并行服务器能够在多处理机上执行多个线程。 1.3任务与分析 一个进程可以创建多个线程,线程与线程间的通信方式比较容易。本设计主要是编写一个多线程的网络通信程序,不同的线程处理不同类型的消息,比如有专门处理TCP 的线程、专门处理UDP消息的线程等。 1

Java线程总结

Java线程总结 在论坛上面常常看到初学者对线程的无可奈何,所以总结出了下面一篇文章,希望对一些正在学习使用java线程的初学者有所帮助。 首先要理解线程首先需要了解一些基本的东西,我们现在所使用的大多数操作系统都属于多任务,分时操作系统。正是由于这种操作系统的出现才有了多线程这个概念。我们使用的w indows,linux就属于此列。什么是分时操作系统呢,通俗一点与就是可以同一时间执行多个程序的操作系统,在自己的电脑上面,你是不是一边听歌,一边聊天还一边看网页呢?但实际上,并不上c pu在同时执行这些程序,c pu只是将时间切割为时间片,然后将时间片分配给这些程序,获得时间片的程序开始执行,不等执行完毕,下个程序又获得时间片开始执行,这样多个程序轮流执行一段时间,由于现在c pu 的高速计算能力,给人的感觉就像是多个程序在同时执行一样。 一般可以在同一时间内执行多个程序的操作系统都有进程的概念。一个进程就是一个执行中的程序,而每一个进程都有自己独立的一块内存空间,一组系统资源。在进程概念中,每一个进程的内部数据和状态都是完全独立的。因此可以想像创建并执行一个进程的系统开像是比较大的,所以线程出现了。在java中,程序通过流控制来执行程序流,程序中单个顺序的流控制称为线程,多线程则指的是在单个程序中可以同时运行多个不同的线程,执行不同的任务。多线程意味着一个程序的多行语句可以看上去几乎在同一时间内同时运行。(你可以将前面一句话的程序换成进程,进程是程序的一次执行过程,是系统运行程序的基本单位) 线程与进程相似,是一段完成某个特定功能的代码,是程序中单个顺序的流控制;但与进程不同的是,同类的多个线程是共享一块内存空间和一组系统资源,而线程本身的数据通常只有微处理器的寄存器数据,以及一个供程序执行时使用的堆栈。所以系统在产生一个线程。或者在各个线程之间切换时,负担要比进程小的多,正因如此,线程也被称为轻负荷进程(light-w eight proc ess)。一个进程中可以包含多个线程。 多任务是指在一个系统中可以同时运行多个程序,即有多个独立运行的任务,每个任务对应一个进程,同进程一样,一个线程也有从创建,运行到消亡的过程,称为线程的生命周期。用线程的状态(state)表明线程处在生命周期的哪个阶段。线程有创建,可运行,运行中,阻塞,死亡五中状态.通过线程的控制与调度可使线程在这几种状态间转化每个程序至少自动拥有一个线程,称为主线程。当程序加载到内存时,启动主线程。 [线程的运行机制以及调度模型] java中多线程就是一个类或一个程序执行或管理多个线程执行任务的能力,每个线程可以独立于其他线程而独立运行,当然也可以和其他线程协同运行,一个类控制着它的所有线程,可以决定哪个线程得到优先级,哪个线程可以访问其他类的资源,哪个线程开始执行,哪个保持休眠状态。 下面是线程的机制图: 线程的状态表示线程正在进行的活动以及在此时间段内所能完成的任务.线程有创建,可运行,运行中,阻塞,死亡五中状态。一个具有生命的线程,总是处于这五种状态之一: 1.创建状态 使用new运算符创建一个线程后,该线程仅仅是一个空对象,系统没有分配资源,称该线程处于创建状态(new thread) 2.可运行状态

多线程实验报告

宁波工程学院电信学院计算机教研室 实验报告 课程名称: Java 2 实验项目: 多线程实验 指导教师: **** 实验位置: 电信楼机房 姓 名: *** 学 号: **** 班 级: **** 日 期: 一、实验目的 1、掌握多线程编程的特点和工作原理; 2、掌握编写线程程序的方法 3、了解线程的调度和执行过程 4、掌握线程同步机理 二、实验环境 windows 记事本,java jdk 1.60版本,cmd 命令运行窗口 三、实验内容 实验一: 应用Java 中线程的概念写一个Java 程序(包括一个测试线程程序类TestThread ,一个Thread 类的子类PrintThread )。在测试程序中用子类PrintThread 创建2个线程,使得其中一个线程运行时打印10次“线程1正在运行”,另一个线程运行时打印5次“线程2正在运行 源程序: public class A { public static void main(String args[]) {

Test1 A1; Test2 A2; A1=new Test1(); A2=new Test2(); A1.start(); A2.start(); } } class PrintThread extends Thread { } class Test1 extends PrintThread { public void run() { for(int i=1;i<=10;i++) { System.out.println("线程1正在运行!"); } } } class Test2 extends PrintThread { public void run() { for(int i=1;i<=5;i++) { System.out.println("线程2正在运行!"); } } } 运行结果:

【2020最新Java面试题资料】15道面试常问的Java多线程面试题

1)现在有T1T2T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行? 这个线程问题通常会在第一轮或电话面试阶段被问到,目的是检测你对”join”方法是否熟悉。这个多线程问题比较简单,可以用join方法实现。 2)在中Lock接口比synchronized块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,以此来保持它的完整性,你会怎样去实现它? lock接口在多线程和并发编程中最大的优势是它们为读和写分别提供了锁,它能满足你写像ConcurrentHashMap这样的高性能数据结构和有条件的阻塞。线程面试的问题越来越会根据面试者的回答来提问。我强烈建议在你去参加多线程的面试之前认真读一下Locks,因为当前其大量用于构建电子交易终统的客户端缓存和交易连接空间。 3)在java中wait和sleep方法的不同? 通常会在电话面试中经常被问到的线程面试问题。最大的不同是在等待时wait会释放锁,而sleep一直持有锁。Wait通常被用于线程间交互,sleep通常被用于暂停执行。 4)用实现阻塞队列。 这是一个相对艰难的多线程面试问题,它能达到很多的目的。第一,它可以检测侯选者是否能实际的用线程写程序;第二,可以检测侯选者对并发场景的理解,并且你可以根据这个问很多问题。如果他用wait()和notify()方法来实现阻塞队列,你可以要求他用最新的Java 5中的并发类来再写一次。 5)用Java写代码来解决生产者——消费者问题。 与上面的问题很类似,但这个问题更经典,有些时候面试都会问下面的问题。在中怎么解决生产者——消费者问题,当然有很多解决方法,我已经分享了一种用阻塞队列实现的方法。有些时候他们甚至会问怎么实现哲学家进餐问题。 6)用编程一个会导致死锁的程序,你将怎么解决? 这是我最喜欢的线程面试问题,因为即使死锁问题在写多线程并发程序时非常普遍,但是很多侯选者并不能写deadlock free code(无死锁代码?),他们很挣扎。只要告诉他们,你有N个资源和N个线程,并且你需要所有的资源来完成一个操作。为了简单这里的n可以替换为2,越大的数据会使问题看起来更复杂。通过避免中的死锁来得到关于死锁的更多信息。

15个顶级Java多线程面试题及回答

Java 线程面试问题 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分。如果你想获得任何股票投资银行的前台资讯职位,那么你应该准备很多关于多线程的问题。在投资银行业务中多线程和并发是一个非常受欢迎的话题,特别是电子交易发展方面相关的。他们会问面试者很多令人混淆的Java线程问题。面试官只是想确信面试者有足够的Java线程与并发方面的知识,因为候选人中有很多只浮于表面。用于直接面向市场交易的高容量和低延时的电子交易系统在本质上是并发的。下面这些是我在不同时间不同地点喜欢问的Java线程问题。我没有提供答案,但只要可能我会给你线索,有些时候这些线索足够回答问题。现在引用Java5并发包关于并发工具和并发集合的问题正在增多。那些问题中ThreadLocal、Blocking Queue、Counting Semaphore和ConcurrentHashMap比较流行。 15个Java多线程面试题及回答 1)现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行? 这个线程问题通常会在第一轮或电话面试阶段被问到,目的是检测你对”join”方法是否熟悉。这个多线程问题比较简单,可以用join方法实现。 2)在Java中Lock接口比synchronized块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,以此来保持它的完整性,你会怎样去实现它? lock接口在多线程和并发编程中最大的优势是它们为读和写分别提供了锁,它能满足你写像ConcurrentHashMap这样的高性能数据结构和有条件的阻塞。Java线程面试的问题越来越会根据面试者的回答来提问。我强烈建议在你去参加多线程的面试之前认真读一下Locks,因为当前其大量用于构建电子交易终统的客户端缓存和交易连接空间。 3)在java中wait和sleep方法的不同? 通常会在电话面试中经常被问到的Java线程面试问题。最大的不同是在等待时wait会释放锁,而sleep一直持有锁。Wait通常被用于线程间交互,sleep通常被用于暂停执行。 4)用Java实现阻塞队列。 这是一个相对艰难的多线程面试问题,它能达到很多的目的。第一,它可以检测侯选者是否能实际的用Java线程写程序;第二,可以检测侯选者对并发场景的理解,并且你可以根据这个问很多问题。如果他用wait()和notify()方法来实现阻塞队列,你可以要求他用最新的Java 5中的并发类来再写一次。 5)用Java写代码来解决生产者——消费者问题。 与上面的问题很类似,但这个问题更经典,有些时候面试都会问下面的问题。在Java中怎么解决生产者——消费者问题,当然有很多解决方法,我已经分享了一种用阻塞队列实现的方法。有些时候他们甚至会问怎么实现哲学家进餐问题。

相关主题
文本预览
相关文档 最新文档