黑马程序员_学习笔记第12天——多线程2
2014-04-17 20:17
411 查看
----------------------
ASP.Net+Android+IOS开发、href="http://edu.csdn.net"target="blank">.Net培训、期待与您交流! ----------------------
1、wait,notify(),notifyAll()都使用在同步中,因为要对持有监视器(锁)的线程操作,所以要使用在同步中,因为只有同步才具有锁。
2、为什么这些操作线程的方法要定义Object类中呢?
因为这些方法在操作同步线程时,都必须要标识他们所操作线程持有的锁,只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒,不可以对不同锁中的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。
[java]
view plaincopy
public class InputOutDemo {
public static void main(String[] args) {
Res r = new Res();
/*Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
<span style="white-space:pre"> </span>*/
new Thread(new Input(r)).start();
new Thread(new Output(r)).start();
}
}
class Res {
private String name;
private String sex;
private boolean flag = false;
public synchronized void set(String name,String sex) {
if(flag)
try {this.wait();}catch (Exception e) {}
this.name = name;
this.sex = sex;
flag = true;
this.notify();
}
public synchronized void out(){
if(!flag)
try {this.wait();}catch (Exception e) {}
System.out.println(name+"........"+sex);
flag = false;
this.notify();
}
}
class Input implements Runnable {
private Res r;
Input(Res r) {
this.r = r;
}
int x ;
public void run() {
while(true) {
/*synchronized(r){
if(r.flag)
try {r.wait();}catch (Exception e) {}*/
if(x==0){
r.set("mike","man");
}
else{
r.set("丽丽","女女女女女");
}
x= (x+1)%2;
/* r.flag = true;
r.notify();*/
// }
}
}
}
class Output implements Runnable {
private Res r;
Output(Res r) {
this.r = r ;
}
public void run() {
while(true) {
/*synchronized(r){
if(!r.flag)
try {r.wait();}catch (Exception e) {}
System.out.println(r.name+"...."+r.sex);
r.flag = false;
r.notify();
}
*/
r.out();
}
}
}
3、对于多个生产者和消费者,为什么要定义while判断标记:因为让被唤醒的线程再一次判断标记。
为什么要定义notifyAll:因为需要唤醒对方线程,因为只用notify,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待。
[java]
view plaincopy
public class ProducerConsumerDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(pro);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource {
private String name ;
private int count = 1 ;
private boolean flag = false;
public synchronized void set(String name ){
while(flag)
try {wait();}catch (Exception e) {}
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"........生产者........."+this.name);
flag = true;
this.notifyAll();
}
public synchronized void out() {
while(!flag)
try {wait();}catch (Exception e) {}
System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name);
flag = false;
this.notifyAll();
}
}
class Producer implements Runnable {
private Resource res;
Producer(Resource res) {
this.res = res;
}
public void run() {
while(true) {
res.set("+商品+");
}
}
}
class Consumer implements Runnable {
private Resource res;
Consumer(Resource res) {
this.res=res;
}
public void run() {
while (true) {
res.out();
}
}
}
4、jdk1.5中提供了多线程升级解决方法,将同步Synchronized替换成了显示的Lock操作,将Object 中的wait,notify,notifyAll,替换成了Condition对象,该对象可以Lock锁,进行获取。该示例中,实现了本方只唤醒对方的操作。
没有Lock之前,一个锁对应一个wait、notify,有了之后,可以对应多个wait、notify
[java]
view plaincopy
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ProducerConsumerDemo2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Resource2 r = new Resource2();
Producer2 pro = new Producer2(r);
Consumer2 con = new Consumer2(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(pro);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource2 {
private String name ;
private int count = 1 ;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition_pro = lock.newCondition();
private Condition condition_con = lock.newCondition();
public synchronized void set(String name )throws InterruptedException{
lock.lock();
try{
while(flag)
condition_pro.await();
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"........生产者........."+this.name);
flag = true;
condition_con.signal();
}
finally{
lock.unlock();//释放锁的动作一定要执行
}
}
public void out() throws InterruptedException{
lock.lock();
try{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name);
flag = false;
condition_pro.signal();
}
finally {
lock.unlock();
}
}
}
class Producer2 implements Runnable {
private Resource2 res;
Producer2(Resource2 res) {
this.res = res;
}
public void run() {
while(true) {
try{
res.set("+商品+");
} catch(InterruptedException e) {
}
}
}
}
class Consumer2 implements Runnable {
private Resource2 res;
Consumer2(Resource2 res) {
this.res=res;
}
public void run() {
while (true) {
try {
res.out();
}catch(InterruptedException e) {
}
}
}
}
5、stop方法已经过时,如何停止线程?
只有一种方法,run方法结束。
开启多线程运行,运行代码通常是循环结构,只要控制住循环,就可以让run方法结束,也就是线程结束。
特殊情况:当线程处于了冻结状态,就不会读取到标记,那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。
Thread类提供该方法interrupt();
[java]
view plaincopy
public class StopThreadDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
StopThread st = new StopThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.start();
t2.start();
int num = 0 ;
while(true) {
if(num++==60) {
//st.changeFlag();
t1.interrupt();
t2.interrupt();
break;
}
System.out.println(Thread.currentThread().getName()+"----main-----");
}
}
}
class StopThread implements Runnable{
private boolean flag = true;
public synchronized void run() {
while(flag) {
try {
wait();
} catch(InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"-----Exception");
flag = false;
}
System.out.println(Thread.currentThread().getName()+"------run------");
}
}
public void changeFlag() {
flag = false;
}
}
6、守护线程:setDaemon(true);该方法必须放在线程开启(start)之前,当正在运行的线程都是守护线程时,java虚拟机退出。
7、join特点:当A线程执行到了B线程的join()方法时,A就会等待,等B线程都执行完,A才会执行。join可以用来临时加入线程执行。
[java]
view plaincopy
public class JoinDemo {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
Demo d = new Demo();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
t1.join();
t2.start();
for(int x=0; x<80 ; x++) {
System.out.println("main...."+x);
}
System.out.println("over");
}
}
class Demo implements Runnable {
public void run() {
for ( int x = 0; x<70; x++) {
System.out.println(Thread.currentThread().getName()+"..."+x);
}
}
}
8、优先级:
设置优先级: t1.setPriority(Thread.MAX_PRIORITY),或MIN_PRIORITY或NORM_PRIORITY,(优先级1-10),正常的都为5级
9、yield()暂停当前正在执行的线程对象,并执行其它线程。Thread.yield()
[java]
view plaincopy
public class ThreadTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
new Thread() {
public void run() {
for(int x=0; x<100; x++) {
System.out.println(Thread.currentThread().getName()+"---1");
}
}
}.start();
for(int x=0; x<100; x++) {
System.out.println(Thread.currentThread()+"----2");
}
Runnable r = new Runnable() {
public void run() {
for(int x=0; x<100; x++) {
System.out.println(Thread.currentThread()+"----3");
}
}
};
new Thread(r).start();
}
}
----------------------
ASP.Net+Android+IOS开发、href="http://edu.csdn.net"target="blank">.Net培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net
ASP.Net+Android+IOS开发、href="http://edu.csdn.net"target="blank">.Net培训、期待与您交流! ----------------------
1、wait,notify(),notifyAll()都使用在同步中,因为要对持有监视器(锁)的线程操作,所以要使用在同步中,因为只有同步才具有锁。
2、为什么这些操作线程的方法要定义Object类中呢?
因为这些方法在操作同步线程时,都必须要标识他们所操作线程持有的锁,只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒,不可以对不同锁中的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。
[java]
view plaincopy
public class InputOutDemo {
public static void main(String[] args) {
Res r = new Res();
/*Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
<span style="white-space:pre"> </span>*/
new Thread(new Input(r)).start();
new Thread(new Output(r)).start();
}
}
class Res {
private String name;
private String sex;
private boolean flag = false;
public synchronized void set(String name,String sex) {
if(flag)
try {this.wait();}catch (Exception e) {}
this.name = name;
this.sex = sex;
flag = true;
this.notify();
}
public synchronized void out(){
if(!flag)
try {this.wait();}catch (Exception e) {}
System.out.println(name+"........"+sex);
flag = false;
this.notify();
}
}
class Input implements Runnable {
private Res r;
Input(Res r) {
this.r = r;
}
int x ;
public void run() {
while(true) {
/*synchronized(r){
if(r.flag)
try {r.wait();}catch (Exception e) {}*/
if(x==0){
r.set("mike","man");
}
else{
r.set("丽丽","女女女女女");
}
x= (x+1)%2;
/* r.flag = true;
r.notify();*/
// }
}
}
}
class Output implements Runnable {
private Res r;
Output(Res r) {
this.r = r ;
}
public void run() {
while(true) {
/*synchronized(r){
if(!r.flag)
try {r.wait();}catch (Exception e) {}
System.out.println(r.name+"...."+r.sex);
r.flag = false;
r.notify();
}
*/
r.out();
}
}
}
3、对于多个生产者和消费者,为什么要定义while判断标记:因为让被唤醒的线程再一次判断标记。
为什么要定义notifyAll:因为需要唤醒对方线程,因为只用notify,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待。
[java]
view plaincopy
public class ProducerConsumerDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(pro);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource {
private String name ;
private int count = 1 ;
private boolean flag = false;
public synchronized void set(String name ){
while(flag)
try {wait();}catch (Exception e) {}
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"........生产者........."+this.name);
flag = true;
this.notifyAll();
}
public synchronized void out() {
while(!flag)
try {wait();}catch (Exception e) {}
System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name);
flag = false;
this.notifyAll();
}
}
class Producer implements Runnable {
private Resource res;
Producer(Resource res) {
this.res = res;
}
public void run() {
while(true) {
res.set("+商品+");
}
}
}
class Consumer implements Runnable {
private Resource res;
Consumer(Resource res) {
this.res=res;
}
public void run() {
while (true) {
res.out();
}
}
}
4、jdk1.5中提供了多线程升级解决方法,将同步Synchronized替换成了显示的Lock操作,将Object 中的wait,notify,notifyAll,替换成了Condition对象,该对象可以Lock锁,进行获取。该示例中,实现了本方只唤醒对方的操作。
没有Lock之前,一个锁对应一个wait、notify,有了之后,可以对应多个wait、notify
[java]
view plaincopy
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ProducerConsumerDemo2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Resource2 r = new Resource2();
Producer2 pro = new Producer2(r);
Consumer2 con = new Consumer2(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(pro);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource2 {
private String name ;
private int count = 1 ;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition_pro = lock.newCondition();
private Condition condition_con = lock.newCondition();
public synchronized void set(String name )throws InterruptedException{
lock.lock();
try{
while(flag)
condition_pro.await();
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"........生产者........."+this.name);
flag = true;
condition_con.signal();
}
finally{
lock.unlock();//释放锁的动作一定要执行
}
}
public void out() throws InterruptedException{
lock.lock();
try{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name);
flag = false;
condition_pro.signal();
}
finally {
lock.unlock();
}
}
}
class Producer2 implements Runnable {
private Resource2 res;
Producer2(Resource2 res) {
this.res = res;
}
public void run() {
while(true) {
try{
res.set("+商品+");
} catch(InterruptedException e) {
}
}
}
}
class Consumer2 implements Runnable {
private Resource2 res;
Consumer2(Resource2 res) {
this.res=res;
}
public void run() {
while (true) {
try {
res.out();
}catch(InterruptedException e) {
}
}
}
}
5、stop方法已经过时,如何停止线程?
只有一种方法,run方法结束。
开启多线程运行,运行代码通常是循环结构,只要控制住循环,就可以让run方法结束,也就是线程结束。
特殊情况:当线程处于了冻结状态,就不会读取到标记,那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。
Thread类提供该方法interrupt();
[java]
view plaincopy
public class StopThreadDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
StopThread st = new StopThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.start();
t2.start();
int num = 0 ;
while(true) {
if(num++==60) {
//st.changeFlag();
t1.interrupt();
t2.interrupt();
break;
}
System.out.println(Thread.currentThread().getName()+"----main-----");
}
}
}
class StopThread implements Runnable{
private boolean flag = true;
public synchronized void run() {
while(flag) {
try {
wait();
} catch(InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"-----Exception");
flag = false;
}
System.out.println(Thread.currentThread().getName()+"------run------");
}
}
public void changeFlag() {
flag = false;
}
}
6、守护线程:setDaemon(true);该方法必须放在线程开启(start)之前,当正在运行的线程都是守护线程时,java虚拟机退出。
7、join特点:当A线程执行到了B线程的join()方法时,A就会等待,等B线程都执行完,A才会执行。join可以用来临时加入线程执行。
[java]
view plaincopy
public class JoinDemo {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
Demo d = new Demo();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
t1.join();
t2.start();
for(int x=0; x<80 ; x++) {
System.out.println("main...."+x);
}
System.out.println("over");
}
}
class Demo implements Runnable {
public void run() {
for ( int x = 0; x<70; x++) {
System.out.println(Thread.currentThread().getName()+"..."+x);
}
}
}
8、优先级:
设置优先级: t1.setPriority(Thread.MAX_PRIORITY),或MIN_PRIORITY或NORM_PRIORITY,(优先级1-10),正常的都为5级
9、yield()暂停当前正在执行的线程对象,并执行其它线程。Thread.yield()
[java]
view plaincopy
public class ThreadTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
new Thread() {
public void run() {
for(int x=0; x<100; x++) {
System.out.println(Thread.currentThread().getName()+"---1");
}
}
}.start();
for(int x=0; x<100; x++) {
System.out.println(Thread.currentThread()+"----2");
}
Runnable r = new Runnable() {
public void run() {
for(int x=0; x<100; x++) {
System.out.println(Thread.currentThread()+"----3");
}
}
};
new Thread(r).start();
}
}
----------------------
ASP.Net+Android+IOS开发、href="http://edu.csdn.net"target="blank">.Net培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net
相关文章推荐
- 转:程序员学习能力提升三要素
- 黑马程序员_学习笔记第11天——多线程1
- Java程序员学习Flex和BlazeDS的十三个理由
- 黑马程序员_java基础知识(四)IO流
- 程序员学习能力提升三要素
- 记一次被虐的很惨的面试
- 程序员学习能力提升三要素
- 黑马程序员-----------------集合框架-List
- 职场必备:公司高层职位的英文缩写
- Java之美[从菜鸟到高手演变]之面试复习提纲
- 黑马程序员_ 选择排序和冒泡排序
- Java面试问题
- 程序员,我们应该如何去学习
- 程序员,我们应该如何去学习(转)
- 程序员,我们应该如何去学习
- 2014年阿里(实习)算法工程师面试
- 黑马程序员-自己总结的java学习笔记(5)继承,接口,多态。
- Debug点滴
- 《黑马程序员》 IO之读取文件中的信息输出到控制台显示
- 《黑马程序员》 IO之文件拷贝