一.线程的方法
1.yield让出cpu
Thread.yield();
2.setPriority()设置线程的优先级
t2.setPriority(Thread.MAX_PRIORITY); //设置最大优先级
t1.setPriority(Thread.MIN_PRIORITY); //设置最小优先级
二.线程之间的通信
1.什么时候需要通信
多个线程并发执行时,在默认情况下CPU是随机切换线程的
如果我们希望他们有规律的执行,就可以使用通信,例如每个线程执行一次打印
2.怎么通信
如果希望线程等待,就调用wait()
如果希望唤醒等待的线程,就调用notify();
这两个方法必须在同步代码中执行,并且使用同步锁对象来调用
private int flag = 1;
public void print1() throws InterruptedException {
synchronized(this){
if(flag != 1)
this.wait(); //当前线程等待
System.out.print("传");
flag = 2; //flag改为2
this.notify(); //随机唤醒另一条线程等待的线程
}
}
public void print2() throws InterruptedException {
synchronized(this) {
if(flag != 2)
this.wait(); //当前线程等待
Thread.sleep(1000);
System.out.print("黑");
flag = 1;
this.notify(); //随机唤醒另一条线程等待的线程
}
}
3.多个线程通信的问题
notify()方法是随机唤醒一个线程
notifyAll()方法是唤醒所有线程
JDK5之前无法唤醒指定的一个线程
如果多个线程之间通信,需要使用notifyAll()通知所有线程,用while来反复判断条件
private int flag = 1;
public void print1() throws InterruptedException {
synchronized(this){
while(flag != 1)
this.wait(); //当前线程等待
System.out.print("传");
flag = 2; //flag改为2
this.notifyAll(); //随机唤醒另一条线程等待的线程
}
}
public void print2() throws InterruptedException {
synchronized(this) {
while(flag != 2)
this.wait(); //线程2等待
System.out.print("黑");
flag = 3;
this.notifyAll(); //随机唤醒另一条线程等待的线程
}
}
public void print3() throws InterruptedException {
synchronized(this) {
while(flag != 3)
this.wait(); //线程3等待
System.out.print("i");
flag = 1;
this.notifyAll(); //随机唤醒另一条线程等待的线程
}
}
/*在同步函数或同步代码块中sleep方法和wait方法的区别
*1,sleep方法必须指定参数(时间,可以是毫秒值和纳秒值),当参数的时间执行后,当前自动醒来
* wait方法可以传参数也可以传参数,如果不传参数直接等待,传参数等待指定时间结束后开始等待
*2,sleep方法执行的时候,不释放锁(睡也要抱着锁睡)
* wait方法执行的时候,释放锁
三.JDK5之后的线程控制
1.同步
使用ReentrantLock类的lock()和unlock()方法进行同步
2.通信
使用ReentrantLock类的newCondition()方法可以获取Condition对象
需要等待的时候使用Condition的await()方法,唤醒的时候用signal()方法
不同的线程使用不同的Condition,这样就能区分唤醒的时候找哪个线程了
private ReentrantLock r = new ReentrantLock();
private Condition c1 = r.newCondition();
private Condition c2 = r.newCondition();
private Condition c3 = r.newCondition();
private int flag = 1;
public void print1() throws InterruptedException {
r.lock();
if(flag != 1)
c1.await(); //当前线程等待
System.out.print("传");
flag = 2; //flag改为2
c2.signal(); //随机唤醒另一条线程等待的线程
r.unlock();
}
public void print2() throws InterruptedException {
r.lock();
if(flag != 2)
c2.await(); //线程2等待
System.out.print("黑");
flag = 3;
c3.signal(); //随机唤醒另一条线程等待的线程
r.unlock();
}
public void print3() throws InterruptedException {
r.lock();
if(flag != 3)
c3.await(); //线程3等待
System.out.print("i");
flag = 1;
c1.signal(); //随机唤醒另一条线程等待的线程
r.unlock();
}
四.GUI
1.事件处理
用户的一个操作就是一个事件,事件处理就是在事件发生的时候程序做出什么反应
事件发生在哪个组件上,哪个组件就是事件源
给事件源添加一个监听器对象
监听器对象中包含若干事件处理方法
如果事件发生了,事件处理方法就会自动执行
3.适配器
a.什么是适配器
在使用监听器的时候,需要定义一个类事件监听器接口.
通常接口中有多个方法,而程序中不一定所有的都用到,但又必须重写,这很繁琐.
适配器简化了这些操作,我们定义监听器时只要继承适配器,然后重写需要的方法即可.
b.适配器原理
适配器就是一个类,实现了监听器接口,所有抽象方法都重写了,但是方法全是空的.
目的就是为了简化程序员的操作,定义监听器时继承适配器,只重写需要的方法就可以了.
五.GUI重点
1.事件处理
事件:用户的一个操作
事件源:被操作的组件
监听器:一个自定义类的对象,实现了监听器接口,包含事件处理方法
把监听器添加在事件源上,当事件发生的时候虚拟机就会自动调用监听器中的事件处理方法
StringBuffer 线程安全的
StringBuild 线程不安全的
vector 线程安全
ArrayList 线程不安全的
hashtable 线程安全的
hashMap 线程不安全的