`

面试总结----多线程

    博客分类:
  • java
 
阅读更多
面试过程中,多线程被问到的概率非常大,差不多都会问的。

下面从线程安全概念、什么情况下会产生多线程安全问题、多线程问题的原因、多线程问题的解决方法、java对多线程的支持、例子等方面来总结多线程。

1、线程安全概念
   线程运行过程中,对共享对象的访问和预期或理论上的值有差别,这时就产生了线程安全问题,下面的例子就是三个线程对变量num产生了并发访问。
package com.yangjianzhou.multiThread.test;

public class ThreadUnsafeTest {

	public static int num = 0;

	public static void main(String[] args) {
		Thread t1 = new Thread(new SubRunnable());
		Thread t2 = new Thread(new SubRunnable());
		t1.start();
		t2.start();
		System.out.println(num);

	}

	static class SubRunnable implements Runnable {
		@Override
		public void run() {
			for (int i = 0; i < 10; i++) {
				num++;
			}

		}
	}
}


输出结果:有时为0,有时为10,有时为20.
输出结果的期望值是10,这时就产生了多线程的安全问题,这里有三个线程:t1、t2、main线程同时对num进行访问(读取和设值),这个变量num在这个多线程环境下就是不安全的。

2.什么情况下会产生多线程安全问题
  上面我们已经通过一个例子展示了多线程的安全问题了,那么什么情况下产生多线程的安全问题呢?
   多个线程对同一个对象的并发访问(读取和设值),这时就有可能产生多线程安全问题。可能是一个线程在读取共享变量值的时候,另外一个线程已经改变了这个变量的值了,这时候读取的值就不是预期的值了,这就产生了多线程安全问题了。

3.多线程问题的原因
   多线程产生的原因看似很简单,但是要弄懂还得从线程执行原理上分析。
  

  上图中展示了两个线程对一个共享变量的存储访问。线程在执行时,首先会将主内存区的共享变量拷贝一个副本到自己的工作线程区,执行的过程中,只会对自己工作线程区中的副本进行操作,什么时候讲共享变量的副本同步到主内存区是不确定的,拿1中的例子来说吧,线程t1执行完后(循环执行完)把num副本同步到主内存,在这之前,其他线程(t2和main线程都没同步主内存num的值),这时,主内存的值就是10,由于线程执行的不确定性,假设线程t1和t2开始时都把num的值读取到自己的工作区,然后t1执行,直到结束,把工作内存的num值同步到主内存,这时线程t2的工作区num副本的值为0,然后t2执行,直到完成,然后同步主内存num的值,这时num的值被覆盖为10,而不是期望的20.这就是多线程并发存储对象产生线程安全问题的实质。

4.多线程问题的解决方法
  多线程安全问题产生了,就需要找到解决方案,我们已经知道了多线程安全问题的实质,线程读取了共享变量错误的值,或者线程设置了共享变量的值而没有及时写入主内存。这里有对象锁、可重入锁、读写锁、信号量等措施来防止多线程安全问题。

5.java对多线程的支持
 
  • java中有关键字final、synchronized、java.util.concurrent包及其子包下面的类都对多线程提供了支持。
  •   
  • volatile不能保证线程安全,这个关键字只能保证变量的可见性和防止指令重排序。
  •   
  • final关键字修饰的变量表示该变量的值不能被改变,当然,但这个关键之被用来修饰一个独享变量的时候,只能保证对象变量在内存中的地址不可以变,而无法保证这个对象中包含的值的被改变。
  •   
  • synchronized 这个关键字只能用来修饰方法,由于每个对象都有一个内部锁,当一个线程进入一个对象的一个synchronized方法中后,就获得了这个对象的内部锁,就去主内存读取共享变量的值(synchronized关键字语法要求),其他线程就无法获取这个对象的内部锁了,只能处于等待状态,当获得内部锁的线程执行完这个方法后,退出方法时,就会讲共享变量值同步到主内存,这时synchronized关键字强制执行的,这时就会释放掉内部锁,其他线程处于等待的线程就会获取这个对象内部锁,进行方法执行,这时该线程工作区的变量值已经是最新的了,因此线程可以安全的执行了。
  •   
  • java.util.concurrent下面的类用到了可重入锁、读写锁和CAS(compare and  swap,这连个操作被设计成一条指令,用到了乐观锁机制)执行。

  • 6.生产者消费者例子
    队列大小为2,两个生产者,一个消费者,因此生产者一般都处于阻塞状态,队列一般都处于满的状态。
    
    生产者:
    package com.yangjianzhou.multiThread.test;
    
    import java.util.concurrent.BlockingQueue;
    
    public class Producer implements Runnable {
    
    	private BlockingQueue<String> queue;
    
    	public Producer(BlockingQueue<String> queue) {
    		this.queue = queue;
    	}
    
    	@Override
    	public void run() {
    		try {
    			for (int i = 0; i < 10; i++) {
    				System.out.println("Producer "+Thread.currentThread().getName()+" , queue.size = "+queue.size());
    				queue.put("break" + Thread.currentThread().getName() + i);
    			}
    		} catch (Exception e) {
    
    		}
    	}
    
    }
    
    消费者:
    package com.yangjianzhou.multiThread.test;
    
    import java.util.concurrent.BlockingQueue;
    
    public class Customer implements Runnable {
    
    	private BlockingQueue<String> queue;
    
    	public Customer(BlockingQueue<String> queue) {
    		this.queue = queue;
    	}
    
    	@Override
    	public void run() {
    		try {
    			for (int i = 0; i < 10; i++) {
    				System.out.println("customer "+Thread.currentThread().getName()+" , queue.size = "+queue.size());
    				queue.take();
    			}
    		} catch (Exception e) {
    
    		}
    	}
    
    }
    
    测试程序:
    package com.yangjianzhou.multiThread.test;
    
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;
    
    public class Test {
    
    	public static void main(String[] args) {
    		BlockingQueue<String> queue = new ArrayBlockingQueue<String>(2);
    		Thread customer = new Thread(new Customer(queue));
    		Thread producer1 = new Thread(new Producer(queue));
    		Thread producer2 = new Thread(new Producer(queue));
    		customer.start();
    		producer1.start();
    		producer2.start();
    	}
    
    }
    
    运行结果:
    customer Thread-0 , queue.size = 0
    Producer Thread-1 , queue.size = 0
    Producer Thread-2 , queue.size = 1
    Producer Thread-2 , queue.size = 2
    Producer Thread-1 , queue.size = 2
    Producer Thread-2 , queue.size = 2
    customer Thread-0 , queue.size = 1
    customer Thread-0 , queue.size = 2
    Producer Thread-1 , queue.size = 2
    Producer Thread-2 , queue.size = 2
    customer Thread-0 , queue.size = 1
    Producer Thread-1 , queue.size = 2
    customer Thread-0 , queue.size = 2
    customer Thread-0 , queue.size = 2
    Producer Thread-2 , queue.size = 2
    customer Thread-0 , queue.size = 2
    Producer Thread-1 , queue.size = 2
    customer Thread-0 , queue.size = 1
    Producer Thread-2 , queue.size = 2
    Producer Thread-1 , queue.size = 2
    customer Thread-0 , queue.size = 2
    customer Thread-0 , queue.size = 1
    Producer Thread-2 , queue.size = 2
    Producer Thread-1 , queue.size = 2
    
    

    • 大小: 12.3 KB
    分享到:
    评论

    相关推荐

      需求分析面试总结--深交所.zip

      针对“需求分析面试总结--深交所.zip”这个主题,我们可以深入探讨以下几个相关知识点: 1. **需求分析**:需求分析是软件工程的第一步,涉及到对用户需求的理解、记录、验证和管理。在这个过程中,分析师需要与...

      Java多线程-知识点梳理和总结-超详细-面试知识点.docx

      "Java多线程-知识点梳理和总结-超详细-面试知识点" Java多线程是Java编程语言中最基本也是最重要的概念之一。多线程编程可以提高程序的执行效率、改善用户体验和提高系统的可扩展性。但是,多线程编程也存在一些...

      大数据面试复习总结

      大数据面试复习---Java基础---集合类、多线程、JVM 大数据面试复习----常问问题分析 大数据面试复习----画重点----思维导图 大数据面试复习----简历编写 大数据面试复习----练习的面试题+笔试题 大数据面试复习----...

      面试知识点总结--线程.pdf

      这有助于在多线程环境下保证数据的一致性。 3. **不推荐使用的线程控制方法**: - `stop()`:不推荐使用,因为它会强制终止线程,可能会导致对象处于不一致的状态,进而引发不可预测的行为。 - `suspend()`:同样...

      java私塾面试题----线程和JSP及EJB部分1

      ### Java私塾面试题解析 —— 线程与EJB部分...以上内容总结了Java私塾面试题中关于线程和EJB的部分,涵盖了线程的基础概念、实现方式、控制方法以及相关的高级特性,希望能帮助读者更好地理解并掌握Java中的线程编程。

      面试总结-JVM .png

      JVM 的运行机制 多线程 JVM 的内存区域 JVM 会创建操作系统的接口创建一个原生线程。JVM 线程和操作系统线程是一一对应的

      软件大数据面试笔试复习资料面试技巧HR面试常问的问题总结面试笔试题整理资料合集.zip

      01大数据面试复习----Java基础---集合类、多线程、JVM 02大数据面试复习----画重点----常问问题分析 03大数据面试复习----画重点----精心制作热门技术思维导图 04大数据面试复习----画重点----56家+真实互联网大公司...

      个人总结40个Java多线程面试问题和答案

      Java多线程面试问题和答案总结 Java多线程是一种高级的编程技术,能够充分发挥多核CPU的优势,防止阻塞,简化模型建立,提高程序的效率和可维护性。下面是40个Java多线程面试问题和答案的总结,涵盖了多线程的基本...

      Java多线程-多线程知识点总结和企业真题

      ### Java多线程知识点总结及企业真题解析 #### 一、知识点总结 ##### (1)多线程相关概念 1. **程序、进程和线程的区分**: - **程序**:为了完成特定的任务而编写的指令集合。它是静态的概念。 - **进程**:...

      面试题总结---javaSE--适用于初学者

      6. **多线程** - **线程的创建**:通过实现Runnable接口或继承Thread类。 - **线程同步**:synchronized关键字保证同一时刻只有一个线程执行特定代码段,防止数据竞争。 - **线程通信**:wait()、notify()和...

      Java面试题资料合集-44套.rar

      java面试-BIO,NIO,AIO,Netty面试题 35道 java面试-Java+最常见的+200++面试题汇总+答案总结汇总 java面试-Java并发编程最全面试题 123道 ...java面试-多线程面试59题(含答案) java面试-设计模式面试题 14道

      c++笔试面试之网络和多线程

      在C++笔试面试中,网络和多线程是两个经常被提及的重要知识点。本篇文档详细列举了关于网络部分的面试题目,同时也涉及了与多线程相关的TCP/IP协议栈的建立和断开过程。以下为详细的知识点总结: 1. TCP服务创建...

      多线程面试59题(含答案).pdf

      多线程面试59题(含答案)是关于多线程编程的知识点总结,涵盖了多线程的基本概念、优点、线程和进程的区别、Java 实现多线程的方式、启动线程方法的区别、终止线程的方式、线程的生命周期、wait()和 sleep()方法的...

      Java面试突击-V3.0_Java面试文档_java面试_面试_

      4. **多线程与并发**:Java提供了丰富的并发工具,如synchronized关键字、volatile变量、ThreadLocal、并发集合(如ConcurrentHashMap)等,掌握这些能解决多线程环境下的同步问题。 5. **内存管理与垃圾回收**:...

      2020面试题总结多线程篇.pdf

      面试题总结——多线程篇 一、多线程实现方式 多线程实现方式主要有四种:继承 Thread 类、实现 Runable 接口、实现 Callable 接口、通过 FutureTask 包装器。这四种方式可以满足不同的需求,例如继承 Thread 类...

      Java面试题-面向对象、多线程.pdf

      1、面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: ...总共90多道题目,包含面向对象、算法、多线程等面试题及详解 大厂面试题集,纯人工手写,分享不易,有问题敬请谅解 。。。。。。。。

      2020最新Java企业面试题汇总-1000多份.txt

      多线程 - **线程创建**:继承Thread类、实现Runnable接口。 - **线程同步**:synchronized关键字、ReentrantLock、Condition。 - **线程间通信**:wait()、notify()、notifyAll()。 - **并发工具类**:...

      java面试必问面试宝典--千方百计

      4. **多线程**: - 线程的创建方式:Thread类、实现Runnable接口。 - 线程状态:新建、就绪、运行、阻塞、终止。 - 同步机制:synchronized、wait()、notify()、notifyAll()。 5. **并发编程**: - volatile...

      Java面试宝典2021-多线程,锁,同步.pdf

      最新java面试关于多线程,锁,同步相关知识总结

      面试知识点总结--java基础类库.pdf

      Java 基础类库面试知识点总结 一、Java IO 流 Java 中有两种类型的流:字节流和字符流。字节流继承于 InputStream...Java 面试题包括了 Java 语言的基础知识、Java 类库、多线程、网络编程、数据库编程等方面的知识。

    Global site tag (gtag.js) - Google Analytics