天天炫斗2016战力提升 一件装备弄完T1再弄T2 和没弄T1直接弄T2 战力会有影响吗 是弄完T1再弄T2

(1)①22.99②11③1④失⑤Na+(2)①氯化钾②硝酸钾③饱和&不变④温度不低于t1℃(3)红& HCl+NaOH==NaCl+H2O&&氯化钠、氯化氢和酚酞试题分析:(1)在元素周期表中的一格中,左上角的数值为其原子序数(质子数或核电荷数);右上角的符号为其元素符号;中间的汉字为该元素的元素名称,最下方的数值表示该元素的相对原子质量。所以①钠的相对原子质量为22.99;②在结构示意图中,圆圈内的数值X为该原子的质子数,可根据前面的图知道其质子数为11;③Y表示钠原子的最外层电子数。因为在原子中质子数=核外电子数;即11=2+8+Y;所以Y为1;④因为钠原子的最外层电子数为1,小于4个,所以易失1个电子。⑤钠离子是由钠原子失去最外层的1个电子形成的,带一个单位的正电荷。根据离子符号的书写特点(先写出元素的元素符号,然后再右上角标明该离子所带的电量及电性),所以钠离子的符号为Na+。(2)①根据二者的溶解度曲线图可知:在t1℃时氯化钾的溶解度要大于硝酸钾的溶解度。②根据图示可知:当温度由t2℃降温到t1℃时,硝酸钾的溶解度的变化值要选大于氯化钾的溶解度的变化值。所以当温度由t2℃降温到t1℃时,两物质的等质量的饱和溶液中,硝酸钾的溶液中析出的固体的质量大。③根据图示可知,在t2℃时氯化钾的溶解度为40g。即在t2℃温度下,氯化钾在100g水里达到饱和状态时所溶解的质量为40g。因此题目中向100g水里50g氯化钾时,最多溶解40g加入溶剂。所以溶液为饱和溶液。&&向溶液中再加入10g水,则水的总质量为110g,最多可溶解氯化钾的质量为44g,所以所得溶液仍为该温度下的氯化钾的饱和溶液。其溶质质量分数不变。④欲配制溶质质量分数为20%的硝酸钾溶液,则要求硝酸钾的溶解度不小于25g。根据硝酸钾的溶解度曲线可知,温度范围为:温度不低于t1℃。(3)氢氧化钠溶液呈碱性,可使酚酞变红。所以溶液原来为红色。随着加入的盐酸与氢氧化钠反应,溶液碱性逐渐减弱;当二者恰好完全反应时,溶液为中性,此时酚酞呈无色;再加入盐酸,则溶液呈酸性,溶液仍为无色。氢氧化钠与盐酸反应的化学方程式为:HCl+NaOH==NaCl+H2O&实验后测得试管中溶液的PH值为2,即溶液呈酸性。所以所含的溶质为氯化钠(为反应的生成物)、氯化氢(加入的过量的盐酸中的溶质)和原有的酚酞。
请在这里输入关键词:
科目:初中化学
来源:不详
题型:单选题
根据下列微粒结构示意图,所获取信息不正确的是&&A.化学性质较稳定B.在化学反应中一般易失电子C.有三个电子层D.其表示的元素在化合物中常显+3价
科目:初中化学
来源:不详
题型:单选题
下列关于四种粒子的结构示意图的说法中正确的是①&&&&&&&&&&&&&&&②&&&&&&&&&&&&&&&③&&&&&&&&&&&&&④A.①③属于不同种元素B.④属于离子,离子符号为Mg2+C.②③的化学性质相似D.②表示的元素在化合物中通常显+1价
科目:初中化学
来源:不详
题型:单选题
某学习小组讨论辨析以下说法:①粗盐和酸雨都是混合物;②沼气和石油都是可再生能源;③冰和干冰既是纯净物又是化合物;④不锈钢和目前流通的硬币都是合金;⑤盐酸和食醋既是化合物又是酸;⑥纯碱和熟石灰都是碱。上述说法正确的是A.①②③④B.①②⑤⑥C.③⑤⑥D.①③④
科目:初中化学
来源:不详
题型:单选题
下列属于纯净物的是&&&&&&&&&&(&&)A.海水 B.空气 C.白酒D.金刚石
科目:初中化学
来源:不详
题型:单选题
下列各图中,“”和“”分别表示两种不同元素的原子,其中表示混合物的是
科目:初中化学
来源:不详
题型:单选题
下列结构示意图所表达的微粒,与所表达的微粒属于同一种元素的是&&&&&&&&&&&A.B.C.D.
科目:初中化学
来源:不详
题型:单选题
下列粒子的结构示意图中属于阴离子的是:
科目:初中化学
来源:不详
题型:单选题
乙烯(C2H4)是一种重要的工业原料,在化学工业上有着重要的用途。乙烯完全燃烧的微观示意图如下所示,则下列说法中,不合理的是&A.该反应属于氧化反应&B.参加反应的&A、B&两物质的分子个数比为&2∶3&C.生成物中&C&物质与&D物质的质量比为&22∶9&D.反应前后氧元素的化合价发生了改变&一、Thread.start()与Thread.run()的区别
通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。然后通过此Thread类调用方法run()来完成其运行操作的,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程终止,而CPU再运行其它线程。
而如果直接用Run方法,这只是调用一个方法而已,程序中依然只有“主线程”这一个线程,并没有开辟新线程,其程序执行路径还是只有一条,这样就没有达到写线程的目的。
测试代码如下
复制代码 代码如下: public class MyThread implements Runnable { public void run() { System.err.println(Thread.currentThread().getName()); } public static void main(String[] args) { MyThread thread = new MyThread(); Thread t1 = new Thread(thread, "Thread-1"); Thread t2 = new Thread(thread, "Thread-2"); t1.run(); t2.run(); } }
输出结果为
>>当前进程为:main
>>当前进程为:main
改为用start方法:
复制代码 代码如下: public class MyThread implements Runnable { public void run() { System.err.println(">>当前进程为:"+Thread.currentThread().getName()); } public static void main(String[] args) { MyThread thread = new MyThread(); Thread t1 = new Thread(thread, "Thread-1"); Thread t2 = new Thread(thread, "Thread-2"); t1.start(); t2.start(); } }
>>当前进程为:Thread-1
>>当前进程为:Thread-2
二、ThreadLocal类详解
ThreadLocal很容易让人望文生义,想当然地认为是一个“本地线程”。其实,ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
下面是线程局部变量(ThreadLocal variables)的关键点:
一个线程局部变量(ThreadLocal variables)为每个线程方便地提供了一个单独的变量。在多个线程操作该变量时候能够互不影响,因为每个线程操作的实际上是改变量的副本。ThreadLocal实例通常作为静态的私有的(private static)字段出现在一个类中,这个类用来关联线程。当多个线程访问ThreadLocal实例时,每个线程维护ThreadLocal提供的独立的变量副本。
下面是测试代码,用于测试:作用于一个对象上面的三个线程来操作同一个ThreadLoacl对象(integer 类型),看是否会出现脏读等现象:
复制代码 代码如下: public class Test implements Runnable { private static ThreadLocal num = new ThreadLocal(); public void run() { num.set(0); for (int i = 0; i < 3; i++) { num.set(num.get() + 1); System.out.println(Thread.currentThread().getName() + ":num=" + num.get()); } } public static void main(String[] args) { Test test = new Test(); Thread t1 = new Thread(test, "Thread-1"); Thread t2 = new Thread(test, "Thread-2"); Thread t3 = new Thread(test, "Thread-3"); t1.start(); t2.start(); t3.start(); } }
运行结果如下:
Thread-3:num=1 Thread-2:num=1 Thread-1:num=1 Thread-2:num=2 Thread-3:num=2 Thread-2:num=3 Thread-1:num=2 Thread-1:num=3 Thread-3:num=3
从上面可以看出,完全没有出现脏读等的现象,因此ThreadLocal线程安全。
常用的使用:当DAO类作为一个单例类时,数据库链接(connection)被每一个线程独立的维护,互不影响。
可以用来控制session的创建和使用,如下ThreadLocal session = new ThreadLocal();
ThreadLoacal与同步机制的比较:
1、在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。
2、而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。
3、概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
三、InvalidMonitorStateException异常
调用wait()/notify()/notifyAll()中的任何一个方法时,如果当前线程没有获得该对象的锁,那么就会抛出IllegalMonitorStateException的异常(也就是说程序在没有执行对象的任何同步块或者同步方法时,仍然尝试调用wait()/notify()/notifyAll()时)。由于该异常是RuntimeExcpetion的子类,所以该异常不一定要捕获(尽管你可以捕获只要你愿意).作为RuntimeException,此类异常不会在wait(),notify(),notifyAll()的方法签名提及。
如下代码,划线的部分会发生该异常,因为没有对该对象执行同步操作。
复制代码 代码如下: public class Common implements Runnable { public synchronized void method1() throws InterruptedException { Thread.sleep(1000); System.out.println("Method 1 called"); Thread.sleep(1000); System.out.println("Method 1 done"); } public synchronized void method2() throws InterruptedException { Thread.sleep(1000); System.err.println("Method 2 called"); Thread.sleep(1000); System.err.println("Method 2 done"); } public void run() { System.out.println("Running " + Thread.currentThread().getName()); try { if (Thread.currentThread().getName().equals("Thread-1")) { this.wait(1000); method1(); } else { method2(); notifyAll(); } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { Common c = new Common(); Thread t1 = new Thread(c, "Thread-1"); Thread t2 = new Thread(c, "Thread-2"); t1.start(); t2.start(); } }
改为一下代码,划线部分: 复制代码 代码如下: public class Common implements Runnable { public synchronized void method1() throws InterruptedException { Thread.sleep(1000); System.out.println("Method 1 called"); Thread.sleep(1000); System.out.println("Method 1 done"); } public synchronized void method2() throws InterruptedException { Thread.sleep(1000); System.err.println("Method 2 called"); Thread.sleep(1000); System.err.println("Method 2 done"); } public void run() { System.out.println("Running " + Thread.currentThread().getName()); try { if (Thread.currentThread().getName().equals("Thread-1")) { synchronized(this){ this.wait(1000); } method1(); } else { method2(); synchronized (this) { notifyAll(); } } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { Common c = new Common(); Thread t1 = new Thread(c, "Thread-1"); Thread t2 = new Thread(c, "Thread-2"); t1.start(); t2.start(); } }
四、sleep()和wait()和suspend()的区别
sleep是Thread类的方法,是线程用来控制自身流程的,比如有一个要报时的线程,每一秒中打印出一个时间,那么我就需要在print方法前面加上一个sleep让自己每隔一秒执行一次。就像个闹钟一样。 sleep() 指示当前线程暂停执行指定时间,把执行机会让给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
wait是Object类的方法,用来线程间的通信,这个方法会使当前拥有该对象锁的线程等待,直到其他线程调用notify方法时再醒来,不过你也可以给它指定一个时间,自动醒来。这个方法主要是用在不同线程之间的调度。对象调用wait()方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
调用wait方法会释放当前线程的锁,其实线程间的通信是靠对象来管理的,所有操作一个对象的线程是这个对象通过自己的wait方法来管理的。就好像这个对象是电视机,三个人是三个线程,那么电视机的遥控器就是这个锁,假如现在A拿着遥控器,电视机调用wait方法,那么A就交出自己的遥控器,由jVM虚拟机调度,遥控器该交给谁。
调用sleep方法不会释放锁,因为sleep()是一个线程用于管理自己的方法,不涉及线程通信。还是上面的例子,如果A拿遥控器的期间,他可以用自己的sleep每隔十分钟调一次台,而在他调台休息的十分钟期间,遥控器还在他的手上,其他人无法获得遥控器。
suspend() 方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁
在以下情况下,持有锁的线程会释放锁:
1. 执行完同步代码块。
2. 在执行同步代码块的过程中,遇到异常而导致线程终止。
3. 在执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程会释放锁,进行对象的等待池。
在以下情况下,线程虽然停止执行,但是线程不会释放锁:
1. 在执行同步代码块的过程中,执行了Thread.sleep()方法,当前线程放弃CPU,开始睡眠,在睡眠中不会释放锁。
2. 在执行同步代码块的过程中,执行了Thread.yield()方法,当前线程放弃CPU,但不会释放锁。
3. 在执行同步代码块的过程中,其他线程执行了当前对象的suspend()方法,当前线程被暂停,但不会释放锁。
五、在静态方法上使用同步
JAVA只识别两种类型的锁:对象锁和类锁。
同步静态方法时会获取该类的"Class”对象,所以当一个线程进入同步的静态方法中时,线程监视器获取类本身的锁,对整个类加锁,其它线程不能进入这个类的任何静态同步方法。它不像实例方法,因为多个线程可以同时访问不同实例同步实例方法。测试代码如下:
复制代码 代码如下: public class Common implements Runnable { public synchronized static void method1() throws InterruptedException { Thread.sleep(1000); System.out.println("Method 1 called"); Thread.sleep(1000); System.out.println("Method 1 done"); } public synchronized static void method2() throws InterruptedException { Thread.sleep(1000); System.err.println("Method 2 called"); Thread.sleep(1000); System.err.println("Method 2 done"); } public void run() { System.out.println("Running " + Thread.currentThread().getName()); try { if (Thread.currentThread().getName().equals("Thread-1")) { method1(); } else { method2(); // Thread.currentThread().notify(); } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { //以下代码创建了不同的对象上的不同线程,用来测试对于同一个类,会不会有锁 Common c1 = new Common(); Common c2 = new Common(); Thread t1 = new Thread(c1, "Thread-1"); Thread t2 = new Thread(c2, "Thread-2"); t1.start(); t2.start(); } }
执行结果如下: Running Thread-2 Running Thread-1 Method 2 called Method 2 done Method 1 called Method 1 done
六、在一个对象上两个线程可以在同一时间分别调用两个不同的同步实例方法吗?
不能,因为一个对象已经同步了实例方法,线程获取了对象的对象锁。所以只有执行完该方法释放对象锁后才能执行其它同步方法。测试代码如下:
复制代码 代码如下: public class Common implements Runnable { public synchronized void method1() throws InterruptedException { Thread.sleep(1000); System.out.println("Method 1 called"); Thread.sleep(1000); System.out.println("Method 1 done"); } public synchronized void method2() throws InterruptedException { Thread.sleep(1000); System.err.println("Method 2 called"); Thread.sleep(1000); System.err.println("Method 2 done"); } public void run() { System.out.println("Running " + Thread.currentThread().getName()); try { if (Thread.currentThread().getName().equals("Thread-1")) { method1(); } else { method2(); // Thread.currentThread().notify(); } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { Common c = new Common(); Thread t1 = new Thread(c, "Thread-1"); Thread t2 = new Thread(c, "Thread-2"); t1.start(); t2.start(); //以下代码作为对比,创建不同的对象,则就不会受对象锁的干扰了 //Common c1 = new Common(); //Common c2 = new Common(); //c1.start(); //c2.start(); } }
执行结果如下: Running Thread-1 Running Thread-2 Method 1 called Method 1 done Method 2 called Method 2 done | Java |
_数据库_运维_开发_IT学习_无忧IT学习网
一起学习!一起进步!
java多线程详细总结
浏览: 210 views
一、Thread.start()与Thread.run()的区别
通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。然后通过此Thread类调用方法run()来完成其运行操作的,这里方法run()称为线程...
一、Thread.start()与Thread.run()的区别
通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。然后通过此Thread类调用方法run()来完成其运行操作的,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程终止,而CPU再运行其它线程。
而如果直接用Run方法,这只是调用一个方法而已,程序中依然只有&主线程&这一个线程,并没有开辟新线程,其程序执行路径还是只有一条,这样就没有达到写线程的目的。
测试代码如下
复制代码 代码如下:
public class MyThread implements Runnable {
public void run() {
System.err.println(Thread.currentThread().getName());
public static void main(String[] args) {
MyThread thread = new MyThread();
Thread t1 = new Thread(thread, &Thread-1&);
Thread t2 = new Thread(thread, &Thread-2&);
输出结果为
&&当前进程为:main
&&当前进程为:main
改为用start方法:
复制代码 代码如下:
public class MyThread implements Runnable {
public void run() {
System.err.println(&&&当前进程为:&+Thread.currentThread().getName());
public static void main(String[] args) {
MyThread thread = new MyThread();
Thread t1 = new Thread(thread, &Thread-1&);
Thread t2 = new Thread(thread, &Thread-2&);
t1.start();
t2.start();
&&当前进程为:Thread-1
&&当前进程为:Thread-2
二、ThreadLocal类详解
ThreadLocal很容易让人望文生义,想当然地认为是一个&本地线程&。其实,ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
下面是线程局部变量(ThreadLocal variables)的关键点:
一个线程局部变量(ThreadLocal variables)为每个线程方便地提供了一个单独的变量。在多个线程操作该变量时候能够互不影响,因为每个线程操作的实际上是改变量的副本。ThreadLocal实例通常作为静态的私有的(private static)字段出现在一个类中,这个类用来关联线程。当多个线程访问ThreadLocal实例时,每个线程维护ThreadLocal提供的独立的变量副本。
下面是测试代码,用于测试:作用于一个对象上面的三个线程来操作同一个ThreadLoacl对象(integer 类型),看是否会出现脏读等现象:
复制代码 代码如下:
public class Test implements Runnable {
private static ThreadLocal&Integer& num = new ThreadLocal&Integer&();
public void run() {
num.set(0);
for (int i = 0; i & 3; i++) {
num.set(num.get() + 1);
System.out.println(Thread.currentThread().getName() + &:num=&
+ num.get());
public static void main(String[] args) {
Test test = new Test();
Thread t1 = new Thread(test, &Thread-1&);
Thread t2 = new Thread(test, &Thread-2&);
Thread t3 = new Thread(test, &Thread-3&);
t1.start();
t2.start();
t3.start();
运行结果如下:
Thread-3:num=1
Thread-2:num=1
Thread-1:num=1
Thread-2:num=2
Thread-3:num=2
Thread-2:num=3
Thread-1:num=2
Thread-1:num=3
Thread-3:num=3
从上面可以看出,完全没有出现脏读等的现象,因此ThreadLocal线程安全。
常用的使用:当DAO类作为一个单例类时,链接(connection)被每一个线程独立的维护,互不影响。
可以用来控制session的创建和使用,如下ThreadLocal&Session& session = new ThreadLocal&Session&();
ThreadLoacal与同步机制的比较:
1、在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。
2、而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。
3、概括起来说,对于多线程资源共享的问题,同步机制采用了&以时间换空间&的方式,而ThreadLocal采用了&以空间换时间&的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
三、InvalidMonitorStateException异常
调用wait()/notify()/notifyAll()中的任何一个方法时,如果当前线程没有获得该对象的锁,那么就会抛出IllegalMonitorStateException的异常(也就是说程序在没有执行对象的任何同步块或者同步方法时,仍然尝试调用wait()/notify()/notifyAll()时)。由于该异常是RuntimeExcpetion的子类,所以该异常不一定要捕获(尽管你可以捕获只要你愿意).作为RuntimeException,此类异常不会在wait(),notify(),notifyAll()的方法签名提及。
如下代码,划线的部分会发生该异常,因为没有对该对象执行同步操作。
复制代码 代码如下:
public class Common implements Runnable {
public synchronized void method1() throws InterruptedException {
Thread.sleep(1000);
System.out.println(&Method 1 called&);
Thread.sleep(1000);
System.out.println(&Method 1 done&);
public synchronized void method2() throws InterruptedException {
Thread.sleep(1000);
System.err.println(&Method 2 called&);
Thread.sleep(1000);
System.err.println(&Method 2 done&);
public void run() {
System.out.println(&Running & + Thread.currentThread().getName());
if (Thread.currentThread().getName().equals(&Thread-1&)) {
this.wait(1000);
method1();
method2();
notifyAll();
} catch (Exception e) {
e.printStackTrace();
public static void main(String[] args) throws InterruptedException {
Common c = new Common();
Thread t1 = new Thread(c, &Thread-1&);
Thread t2 = new Thread(c, &Thread-2&);
t1.start();
t2.start();
改为一下代码,划线部分:
复制代码 代码如下:
public class Common implements Runnable {
public synchronized void method1() throws InterruptedException {
Thread.sleep(1000);
System.out.println(&Method 1 called&);
Thread.sleep(1000);
System.out.println(&Method 1 done&);
public synchronized void method2() throws InterruptedException {
Thread.sleep(1000);
System.err.println(&Method 2 called&);
Thread.sleep(1000);
System.err.println(&Method 2 done&);
public void run() {
System.out.println(&Running & + Thread.currentThread().getName());
if (Thread.currentThread().getName().equals(&Thread-1&)) {
synchronized(this){
this.wait(1000);
method1();
method2();
synchronized (this) {
notifyAll();
} catch (Exception e) {
e.printStackTrace();
public static void main(String[] args) throws InterruptedException {
Common c = new Common();
Thread t1 = new Thread(c, &Thread-1&);
Thread t2 = new Thread(c, &Thread-2&);
t1.start();
t2.start();
四、sleep()和wait()和suspend()的区别
sleep是Thread类的方法,是线程用来控制自身流程的,比如有一个要报时的线程,每一秒中打印出一个时间,那么我就需要在print方法前面加上一个sleep让自己每隔一秒执行一次。就像个闹钟一样。 sleep() 指示当前线程暂停执行指定时间,把执行机会让给其他线程,但是状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
wait是Object类的方法,用来线程间的通信,这个方法会使当前拥有该对象锁的线程等待,直到其他线程调用notify方法时再醒来,不过你也可以给它指定一个时间,自动醒来。这个方法主要是用在不同线程之间的调度。对象调用wait()方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
调用wait方法会释放当前线程的锁,其实线程间的通信是靠对象来管理的,所有操作一个对象的线程是这个对象通过自己的wait方法来管理的。就好像这个对象是电视机,三个人是三个线程,那么电视机的遥控器就是这个锁,假如现在A拿着遥控器,电视机调用wait方法,那么A就交出自己的遥控器,由jVM虚拟机调度,遥控器该交给谁。
调用sleep方法不会释放锁,因为sleep()是一个线程用于管理自己的方法,不涉及线程通信。还是上面的例子,如果A拿遥控器的期间,他可以用自己的sleep每隔十分钟调一次台,而在他调台休息的十分钟期间,遥控器还在他的手上,其他人无法获得遥控器。
suspend() 方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁。此时,其他任何线程都不能访问锁定的资源,除非被&挂起&的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁
在以下情况下,持有锁的线程会释放锁:
1. 执行完同步代码块。
2. 在执行同步代码块的过程中,遇到异常而导致线程终止。
3. 在执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程会释放锁,进行对象的等待池。
在以下情况下,线程虽然停止执行,但是线程不会释放锁:
1. 在执行同步代码块的过程中,执行了Thread.sleep()方法,当前线程放弃CPU,开始睡眠,在睡眠中不会释放锁。
2. 在执行同步代码块的过程中,执行了Thread.yield()方法,当前线程放弃CPU,但不会释放锁。
3. 在执行同步代码块的过程中,其他线程执行了当前对象的suspend()方法,当前线程被暂停,但不会释放锁。
五、在静态方法上使用同步
只识别两种类型的锁:对象锁和类锁。
同步静态方法时会获取该类的&Class&对象,所以当一个线程进入同步的静态方法中时,线程监视器获取类本身的锁,对整个类加锁,其它线程不能进入这个类的任何静态同步方法。它不像实例方法,因为多个线程可以同时访问不同实例同步实例方法。测试代码如下:
复制代码 代码如下:
public class Common implements Runnable {
public synchronized static void method1() throws InterruptedException {
Thread.sleep(1000);
System.out.println(&Method 1 called&);
Thread.sleep(1000);
System.out.println(&Method 1 done&);
public synchronized static void method2() throws InterruptedException {
Thread.sleep(1000);
System.err.println(&Method 2 called&);
Thread.sleep(1000);
System.err.println(&Method 2 done&);
public void run() {
System.out.println(&Running & + Thread.currentThread().getName());
if (Thread.currentThread().getName().equals(&Thread-1&)) {
method1();
method2();
// Thread.currentThread().notify();
} catch (Exception e) {
e.printStackTrace();
public static void main(String[] args) throws InterruptedException {
//以下代码创建了不同的对象上的不同线程,用来测试对于同一个类,会不会有锁
Common c1 = new Common();
Common c2 = new Common();
Thread t1 = new Thread(c1, &Thread-1&);
Thread t2 = new Thread(c2, &Thread-2&);
t1.start();
t2.start();
执行结果如下:
Running Thread-2
Running Thread-1
Method 2 called
Method 2 done
Method 1 called
Method 1 done
六、在一个对象上两个线程可以在同一时间分别调用两个不同的同步实例方法吗?
不能,因为一个对象已经同步了实例方法,线程获取了对象的对象锁。所以只有执行完该方法释放对象锁后才能执行其它同步方法。测试代码如下:
复制代码 代码如下:
public class Common implements Runnable {
public synchronized void method1() throws InterruptedException {
Thread.sleep(1000);
System.out.println(&Method 1 called&);
Thread.sleep(1000);
System.out.println(&Method 1 done&);
public synchronized void method2() throws InterruptedException {
Thread.sleep(1000);
System.err.println(&Method 2 called&);
Thread.sleep(1000);
System.err.println(&Method 2 done&);
public void run() {
System.out.println(&Running & + Thread.currentThread().getName());
if (Thread.currentThread().getName().equals(&Thread-1&)) {
method1();
method2();
// Thread.currentThread().notify();
} catch (Exception e) {
e.printStackTrace();
public static void main(String[] args) throws InterruptedException {
Common c = new Common();
Thread t1 = new Thread(c, &Thread-1&);
Thread t2 = new Thread(c, &Thread-2&);
t1.start();
t2.start();
//以下代码作为对比,创建不同的对象,则就不会受对象锁的干扰了
//Common c1 = new Common();
//Common c2 = new Common();
//c1.start();
//c2.start();
执行结果如下:
Running Thread-1
Running Thread-2
Method 1 called
Method 1 done
Method 2 called
Method 2 done
& | & & | & & | & & | & & | & & | & & | & & | & & | & & | & & | & & | & & | &
最热门文章
34141 views
9842 views
7392 views
4366 views
3534 views
3432 views
3064 views
2621 views
友情链接 |
本站进行132次查询

我要回帖

更多关于 天天炫斗最高战力 的文章

 

随机推荐