黑么程序员_关于线程的学习
2011-11-03 16:27
232 查看
----------------------- android培训、java培训、java学习型技术博客、期待与您交流! ---------------------
通过在API的查找,java已经对线程这类事务的描述,就是thread类。
2 创建线程的2种方法
第一是继承thread类。步骤为:
1 定义类继承thread类。
2 复习thread类中的run方法。
3调用线程的start方法,该方法有两个作用:启动线程,和调用run方法。
第二种方式是实现runable接口。步骤为:
1 定义类实现r借口。
2 复习runable类中的run方法。
3 通过thread类建立线程的对象
4将runable接口的子类的对象做为实参传递给thread类的构造函数。
5 调用thread类的start的方法,开启线程并调用runable借口子类的run方法。
3 实现方式和继承有什么区别?
继承thread:线程代码放在子类的run方法中。
实现runable:线程代码存放在接口子类run中。
问题的原因是:
当多条语句操作一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来,导致共享数据错误,
解决办法:
对多条操作共享数据的语句只能让一个线程都执行完了才,才能让别的另一线程执行完,别的线程不可以执行。
6 java对多线程的安全问题提供了专业的解决办法,就是提供的synchronize(){需要被同步的代码}
7 同步的前提:
1不需要有2个和两个以上的线程。
2必须是抖个线程使用同一个锁。
3必须保证同步中只有一个线程在运行。
8 如果同步函数被静态修饰后,使用的是什么锁?
通过验证,发现不在是this,因为静态方法中不可以定义this。静态进内存中也没有对象,但是一定有该类对应的字节码文件的对象,类名.class。
9 线程间的通讯:
其实就是多个线程操作同一个之源,但是操作的动作不一样。
10 如何停止线程?
只有一种,run方法结束。
开启多线程运行,运行的代码通常是循环结构,只需要控制循环,就可以让run方法结束,也就是线程结束。 特殊情况:当线程处于冻结状态时,线程就不会结束。当没有指定的方式让冻结的线程回复到运行状态时,这时需要对冻 结进行解除,强制让线程回复到运行状态,这样就可以操作标记,让线程结束,thread类提供了interrupet()。
11 关于join
当A线程执行到B线程的join方法时,A就会等待,等B线程执行完,A才会开始。
一下是关于多线程的例子
写出一组模拟生产者/消费者的协作程序
其中包括一个WoTou.java,代表消息
一个MsgQueue.java,为一个队列,提供put(Message msg)方法和get()方法
一个Produer.java,为生产者线程,在其run方法中每隔1秒产生一个Message对像并放入MsgQueue队列
一个Consumer.java为消费者线程,在其run方法中不断从MsgQueue队列中获取Message对像,并显示在屏幕上
一个TestMain.java,在其main方法中,启动2个Produer线程和2个消费者线程.
要求:
对于MsgQueue.java,队列的长度为10,当消息超过10个时,put()方法需要阻塞:当消息队列为空时,
get()方法需要阻塞。
public class ProducerConsumer {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
Producer p1= new Producer(ss,"p1");
Consumer c1= new Consumer(ss,"c1");
Producer p2= new Producer(ss,"p2");
Consumer c2= new Consumer(ss,"c2");
}
}
class WoTou<T> {
int id;
WoTou(int id) {
this.id = id;
}
public String toString() {
return "WoTou : " + id;
}
}
class SyncStack {
int index = 0;
WoTou[] arrWT = new WoTou[6];
public void push(WoTou wt) {
while(index == arrWT.length) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
arrWT[index] = wt;
index ++;
}
public WoTou pop() {
while(index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
index--;
return arrWT[index];
}
}
class Producer implements Runnable {
SyncStack ss = null;
String a;
Producer(SyncStack ss,String a) {
this.ss = ss;
this.a= a;
Thread t=new Thread(this,a);
t.start();
}
public void run() {
for(int i=0; i<10; i++) {
synchronized(ss){
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println(a+" 生产了:" + wt);}
try {
Thread.sleep((int)(Math.random() * 200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
SyncStack ss = null;
String a;
Thread t;
Consumer(SyncStack ss,String a) {
this.ss = ss;
this.a= a;
t=new Thread(this,a);
t.start();
}
public void run() {
for(int i=0; i<10; i++) {
synchronized(ss){
WoTou wt = ss.pop();
System.out.println(a+" 消费了: " + wt);}
try {
Thread.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
p1 生产了:WoTou : 0
p2 生产了:WoTou : 0
p3 生产了:WoTou : 0
c1 消费了: WoTou : 0
c1 消费了: WoTou : 0
p3 生产了:WoTou : 1
c1 消费了: WoTou : 1
c1 消费了: WoTou : 0
p3 生产了:WoTou : 2
p1 生产了:WoTou : 1
c1 消费了: WoTou : 1
p2 生产了:WoTou : 1
p2 生产了:WoTou : 2
c1 消费了: WoTou : 2
p2 生产了:WoTou : 3
p3 生产了:WoTou : 3
c1 消费了: WoTou : 3
p3 生产了:WoTou : 4
p2 生产了:WoTou : 4
c1 消费了: WoTou : 4
c1 消费了: WoTou : 4
p1 生产了:WoTou : 2
c1 消费了: WoTou : 2
p2 生产了:WoTou : 5
p3 生产了:WoTou : 5
p2 生产了:WoTou : 6
栈里有6个
首先是观看传智播客老师视频后的一些总结:
1 如何在自定义的代码中,自定义一个线程的问题:通过在API的查找,java已经对线程这类事务的描述,就是thread类。
2 创建线程的2种方法
第一是继承thread类。步骤为:
1 定义类继承thread类。
2 复习thread类中的run方法。
3调用线程的start方法,该方法有两个作用:启动线程,和调用run方法。
第二种方式是实现runable接口。步骤为:
1 定义类实现r借口。
2 复习runable类中的run方法。
3 通过thread类建立线程的对象
4将runable接口的子类的对象做为实参传递给thread类的构造函数。
5 调用thread类的start的方法,开启线程并调用runable借口子类的run方法。
3 实现方式和继承有什么区别?
继承thread:线程代码放在子类的run方法中。
实现runable:线程代码存放在接口子类run中。
4 实现方法的好处:避免了单继承的局限性,在定义线程时建议用实现法。
5 多线程出现的安全问题:问题的原因是:
当多条语句操作一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来,导致共享数据错误,
解决办法:
对多条操作共享数据的语句只能让一个线程都执行完了才,才能让别的另一线程执行完,别的线程不可以执行。
6 java对多线程的安全问题提供了专业的解决办法,就是提供的synchronize(){需要被同步的代码}
7 同步的前提:
1不需要有2个和两个以上的线程。
2必须是抖个线程使用同一个锁。
3必须保证同步中只有一个线程在运行。
8 如果同步函数被静态修饰后,使用的是什么锁?
通过验证,发现不在是this,因为静态方法中不可以定义this。静态进内存中也没有对象,但是一定有该类对应的字节码文件的对象,类名.class。
9 线程间的通讯:
其实就是多个线程操作同一个之源,但是操作的动作不一样。
10 如何停止线程?
只有一种,run方法结束。
开启多线程运行,运行的代码通常是循环结构,只需要控制循环,就可以让run方法结束,也就是线程结束。 特殊情况:当线程处于冻结状态时,线程就不会结束。当没有指定的方式让冻结的线程回复到运行状态时,这时需要对冻 结进行解除,强制让线程回复到运行状态,这样就可以操作标记,让线程结束,thread类提供了interrupet()。
11 关于join
当A线程执行到B线程的join方法时,A就会等待,等B线程执行完,A才会开始。
一下是关于多线程的例子
写出一组模拟生产者/消费者的协作程序
其中包括一个WoTou.java,代表消息
一个MsgQueue.java,为一个队列,提供put(Message msg)方法和get()方法
一个Produer.java,为生产者线程,在其run方法中每隔1秒产生一个Message对像并放入MsgQueue队列
一个Consumer.java为消费者线程,在其run方法中不断从MsgQueue队列中获取Message对像,并显示在屏幕上
一个TestMain.java,在其main方法中,启动2个Produer线程和2个消费者线程.
要求:
对于MsgQueue.java,队列的长度为10,当消息超过10个时,put()方法需要阻塞:当消息队列为空时,
get()方法需要阻塞。
public class ProducerConsumer {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
Producer p1= new Producer(ss,"p1");
Consumer c1= new Consumer(ss,"c1");
Producer p2= new Producer(ss,"p2");
Consumer c2= new Consumer(ss,"c2");
}
}
class WoTou<T> {
int id;
WoTou(int id) {
this.id = id;
}
public String toString() {
return "WoTou : " + id;
}
}
class SyncStack {
int index = 0;
WoTou[] arrWT = new WoTou[6];
public void push(WoTou wt) {
while(index == arrWT.length) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
arrWT[index] = wt;
index ++;
}
public WoTou pop() {
while(index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
index--;
return arrWT[index];
}
}
class Producer implements Runnable {
SyncStack ss = null;
String a;
Producer(SyncStack ss,String a) {
this.ss = ss;
this.a= a;
Thread t=new Thread(this,a);
t.start();
}
public void run() {
for(int i=0; i<10; i++) {
synchronized(ss){
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println(a+" 生产了:" + wt);}
try {
Thread.sleep((int)(Math.random() * 200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
SyncStack ss = null;
String a;
Thread t;
Consumer(SyncStack ss,String a) {
this.ss = ss;
this.a= a;
t=new Thread(this,a);
t.start();
}
public void run() {
for(int i=0; i<10; i++) {
synchronized(ss){
WoTou wt = ss.pop();
System.out.println(a+" 消费了: " + wt);}
try {
Thread.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
p1 生产了:WoTou : 0
p2 生产了:WoTou : 0
p3 生产了:WoTou : 0
c1 消费了: WoTou : 0
c1 消费了: WoTou : 0
p3 生产了:WoTou : 1
c1 消费了: WoTou : 1
c1 消费了: WoTou : 0
p3 生产了:WoTou : 2
p1 生产了:WoTou : 1
c1 消费了: WoTou : 1
p2 生产了:WoTou : 1
p2 生产了:WoTou : 2
c1 消费了: WoTou : 2
p2 生产了:WoTou : 3
p3 生产了:WoTou : 3
c1 消费了: WoTou : 3
p3 生产了:WoTou : 4
p2 生产了:WoTou : 4
c1 消费了: WoTou : 4
c1 消费了: WoTou : 4
p1 生产了:WoTou : 2
c1 消费了: WoTou : 2
p2 生产了:WoTou : 5
p3 生产了:WoTou : 5
p2 生产了:WoTou : 6
栈里有6个
----------------------- android培训、java培训、java学习型技术博客、期待与您交流! ---------------------
相关文章推荐
- 一骑绝尘引发的思考–关于hive程序员是否需要学习mapreduce
- 一个.Net程序员关于学习的思考顺带思考人生
- 关于职业规划,尤其值得我们程序员学习、思考
- 关于线程Thread的学习
- 一个.Net程序员关于学习的思考顺带思考人生
- 转自知乎一朋友关于java程序员初级学习的一些见解
- 关于线程学习总结
- 关于职业规划,尤其值得我们程序员学习、思考
- 黑马程序员----关于构造函数与的学习以及this指针在构造函数间的调用规则
- 关于学习进程控制和线程控制的小结
- 关于进程、线程的学习分享
- 关于THREAD线程中CurrentCulture与CurrentUICulture的学习及疑问
- 【非凡程序员】 关于今天学习指针的一些自我认知的问题,和学习Xcode的感悟
- 关于THREAD线程中CurrentCulture与CurrentUICulture的学习
- 关于线程锁的学习
- 关于java 线程学习
- 今日学习:关于C#多线程之一——异步委托
- 下列哪些语句关于内存回收的说明是正确的? (b ) A、 程序员必须创建一个线程来释放内存
- 从学生到程序员(三) 关于学习
- (转51cto)一个.Net程序员关于学习的思考顺带思考人生