java3线程答案
来源:互联网 发布:yum 安装vim 编辑:程序博客网 时间:2024/05/21 21:36
22.JNInative是方法修饰符。Native方法是由另外一种语言(如c/c++,FORTRAN,汇编)实现的本地方法。
1)、继承Thread类实现多线程
继承Thread类的方法尽管被我列为一种多线程实现方式,但Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。例如
- ublic class MyThread extends Thread {
- public void run() {
- System.out.println("MyThread.run()");
- }
- }
- MyThread myThread1 = new MyThread();
- MyThread myThread2 = new MyThread();
- myThread1.start();
- myThread2.start();
为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例:
3)类似的,无返回值的任务必须Runnable接口,可返回值的任务必须实现Callable接口,执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了,再结合线程池接口ExecutorService就可以实现传说中有返回结果的多线程了,ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。
23.线程的状态转换
(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。由于notify()只是唤醒一个线程,但我们由不能确定具体唤醒的是哪一个线程,也许我们需要唤醒的线程不能够被唤醒,因此在实际使用时,一般都用notifyAll()方法,唤醒有所线程)
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。当线程刚进入可运行状态(注意,还没运行),发现将要调用的资源被synchroniza(同步),获取不到锁标记,将会立即进入锁池状态,
(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。
线程同步方法:synchronize与wait-notifysynchronize与lock:自动与手动释放锁
sleep是线程类不会释放锁对象
wait是Object类方法会释放锁对象
24.如何停止一个线程
使用interrupt方法终止线程
(1)线程处于阻塞状态,如使用了sleep方
法。
(2)使用while(!isInterrupted())
{……}来判断线程是否被中断。
在第一种情况下使用interrupt方法,sleep
方法将抛出一个InterruptedException例外,
而在第二种情况下线程将直接退出
1 )处于运行状态的线程停止:
线程需要通过设置停止变量的方式
2)处于可中断等待线程的停止:线程调用了sleep或wait方法,这些方法可抛出InterruptedException;则可以通过调用Thread的interrupt方法让等待方法抛出InterruptedException异常,然后在循环外截获并处理异常
3) 处于IO阻塞状态线程的停止:线程调用了IO的read操作或者socket的accept操作,处于阻塞状态。Java的InterruptableChanel接口提供了这样的机制
25.如何保证线程安全
不要跨线程访问共享变量
使共享变量是final类型的
将共享变量的操作加上同步
volatile声明的数值类型变量进行运算, 往往是不安全的(volatile只能保证可见性,不能保证原子性
当一个线程请求获得它自己占有的锁时(同一把锁的嵌套使用), 我们称该锁为可重入锁
提供了可重入锁的java实现-ReentrantLock. 每个共享变量,都应该由一个唯一确定的锁保护.创建与变量相同数目的ReentrantLock, 使他们负责每个变量的线程安全.
使用ThreadLocal变量确保线程封闭性(封闭线程往往是比较安全的, 但一定程度上会造成性能损耗)封闭对象的例子在实际使用过程中
在并发编程中, 需要容器支持的时候, 优先考虑使用jdk并发容器(ConcurrentHashMap, ConcurrentLinkedQueue, CopyOnWriteArrayList.但是他们支持的并发实现并不一定意味着操作的原子性,他们只是保证数据结构不被破坏
http://blog.csdn.net/fp196391196391/article
/details/39493761
26.Synchronized如何使用
1)方法声明时使用,放在范围操作符(public等)之后,返回类型声明(void等)之前.这时,线程获得的是成员锁,即一次只能有一个线程进入该方法,其他线程要想在此时调用该方法,只能排队等候,当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入.
public synchronized void synMethod() {
//方法体
}
2)对某一代码块使用,synchronized后跟括号,括号里是变量,这样,一次只有一个线程进入该代码块.此时,线程获得的是成员锁
public int synMethod(int a1){
synchronized(a1) {
//一次只能有一个线程进入
}
}
3)synchronized后面括号里是一对象,此时,线程获得的是对象锁
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName());
}
4) synchronized后面括号里是类,此时,线程获得的是对象锁
public ArrayWithLockOrder(int[] a)
{
arr = a;
synchronized(ArrayWithLockOrder.class) {//-----这里
num_locks++; // 锁数加 1。
lock_order = num_locks; // 为此对象实例设置唯一的 lock_order。
}
27.
synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中
28.sleep和wait的区别在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态;
这两个方法来自不同的类分别是,sleep来
自Thread类,和wait来自Object类。
最主要是sleep方法没有释放锁,而wait方
法释放了锁,
、使用范围:wait,notify和notifyAll只能
在同步控制方法或者同步控制块里面使用,
而sleep可以在任何地方使用
29.守护进程:
守护线程:守护线程则是用来服务用户线程
的,如果没有其他用户线程在运行,那么就
没有可服务对象,也就没有理由继续下去。
setDaemon(boolean on)方法必须在线程
启动之前调用,当线程正在运行时调用会产
生异常。
30.Java线程池技术及原理
使用线程池的好处:
1.减少在创建和销毁线程上所花的时间以及系统资源的开销
2.如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存以及”过度切换”。
JDK自带线程池总类
1)newFixedThreadPool创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
2)newCachedThreadPool创建一个可缓存的线程池。工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE
3)newSingleThreadExecutor创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行(我觉得这点是它的特色)
4)newScheduleThreadPool创建一个定长的线程池,
31.java并发包concurrent及常用的类
http://www.cnblogs.com/vijozsoft/p/558562
0.html//集合
Java内存模型:
java内存模型中规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存(可以与前面将的处理器的高速缓存类比),线程的工作内存中保存了该线程使用到的变量到主内存副本拷贝,线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,而不能直接读写主内存中的变量。不同线程之间无法直接访问对方工作内存中的变量,线程间变量值的传递均需要在主内存来完成,线程、主内存和工作内存的交互关系如下图所示
volatile关键字
可见性。对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。
原子性:对任意单个volatile变量的读/写具有原子性,
下面对volatile写和volatile读的内存语义做个总结:
线程A写一个volatile变量,实质上是线程A向接下来将要读这个volatile变量的某个线程发出了(其对共享变量所在修改的)消息。
线程B读一个volatile变量,实质上是线程B接收了之前某个线程发出的(在写这个volatile变量之前对共享变量所做修改的)消息。
线程A写一个volatile变量,随后线程B读这个volatile变量,这个过程实质上是线程A通过主内存向线程B发送消息。
1) ConcurrentHashMap
ConcurrentHashMap是线程安全的HashMap的实现,默认构造同样有initialCapacity和loadFactor属性,不过还多了一个concurrencyLevel属性,三属性默认值分别为16、0.75及16。其内部使用锁分段技术,维持这锁Segment的数组,在Segment数组中又存放着Entity[]数组,内部hash算法将数据较均匀分布在不同锁中。
oncurrentHashMap默认情况下采用将数据分为16个段进行存储,并且16个段分别持有各自不同的锁Segment,锁仅用于put和remove等改变集合对象的操作,基于volatile及HashEntry链表的不变性实现了读取的不加锁。这些方式使得ConcurrentHashMap能够保持极好的并发支持,尤其是对于读远比插入和删除频繁的Map而言,而它采用的这些方法也可谓是对于Java内存模型、并发机制深刻掌握的体现。
ConcurrentLinkedQueue是一个基于链接节点的、无界的、线程安全的队列
- java3线程答案
- java3
- java3
- java3
- java3
- java3
- java3
- java3
- java3
- Java3
- java3
- java3
- java3
- java3
- java3
- java3.2
- 初识JAVA3
- 复习java3
- UVA 816 bfs
- 自动化测试
- Android开发中常用到的一些工具类整理
- ros中launch文件
- harris角点
- java3线程答案
- tableau:柱图的两种实现方式
- POJ1837
- 怎样实现EDIUS中音频滤镜快速使用
- HDU5781 ATM Mechine
- openvpn基于MySQL的用户名/密码验证方式
- jsp 检测登录浏览器版本
- kindeditor编辑器的应用
- eclipse中使用maven管理android项目