五、多线程、网络
30..多线程和并行程序设计
(1)创建任务、线程:
任务从线程运行,一个任务类必须实现Runnable接口。
(2)Thread类:
Thread类实现了Runnable,但不推荐通过继承Thread类来定义线程类。将任务从线程中分离出来比较好。
stop()、suspend()、resume()方法不安全,为替代Thread使用,通过给Thread变量赋值null来表明它已经停止。
yield()方法:为其他线程临时让出CPU时间。
sleep()方法:InterruptedException必检异常(interrupt()被调用时,但极少发生)
join()方法:使一个线程等待另一个线程的结束。(等待该线程结束)
优先级:
默认:继承
1-10
MIN_PRIORITY、NORM_PRIORITY(主线程优先级为它)、MAX_PRIORITY:1、5、10
选择运行当前优先级最高的,相同优先级循环调度(用循环队列给它们分配相同的CPU份额)。
为避免竞争现象,高优先级的线程必须定时调用sleep方法或yield方法,来给低优先级、相同优先级线程运行机会。
(3)javafx 动画、线程:
可以使用Timeline对象控制动画,也可以使用线程来控制动画。
public class PrOne extends Application{
private String text="";
@Override
public void start(Stage ps){
StackPane pane=new StackPane();
Label lblText=new Label("fun");//--------
pane.getChildren().add(lblText);
new Thread(new Runnable(){----------------------------------------------------------------------------
@Override
public void run(){
try{
while(true){
if(lblText.getText().trim().length()==0)
text="welcome";
else
text="";
Platform.runLater(new Runnable(){----------
@Override
public void run(){
lblText.setText(text);
}
}); ///-------------
Thread.sleep(200);
}
}
catch(InterruptedException e){
}
}
}).start();//--------------------------------------------------------------------------------------------
Scene s=new Scene(pane,200,50);
ps.setTitle("FlashText");
ps.setScene(s);
ps.show();
}
(4)线程池:P322
如果仅需要为一个任务创建一个线程,Thread类。多个任务创建线程,最好使用线程池。
(5)线程同步:P324
竞争状态、线程安全的:
synchronized:实例方法、静态方法 ctrl+f:同步、对象加锁、对象锁
①public synchronized void fun();
②同步块:
synchronized(expr){//expr:一个对象的引用
statements;
}
(6)利用加锁同步:
同步的实例方法在执行之前都隐式地需要一个加在实例上的锁。
公平策略:
public void deposit(int amount) {
lock.lock(); //
try {
int newBalance = balance + amount;
Thread.sleep(5);
balance = newBalance;
}
catch (InterruptedException ex) {
}
finally {
lock.unlock(); //
}
}
(7)线程间协作:P330
利用条件进行线程间通信
例1:提款取款
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
public class C{
private static Account account=new Account();
public static void main(String[] args){
ExecutorService executor=Executors.newFixedThreadPool(2);//
executor.execute(new DepositTask());
executor.execute(new WithdrawTask());
executor.shutdown();
System.out.println(account.getBalance());
}
public static class DepositTask implements Runnable{//------
@Override
public void run(){
try{
while(true){//------
account.deposit( (int)(Math.random() * 10) + 1 );
Thread.sleep(1000);
}
}
catch(InterruptedException ex){
ex.printStackTrace();
}
}
}
public static class WithdrawTask implements Runnable {//------
public void run() {
while (true) {//------
account.withDraw((int)(Math.random() * 10) + 1);
}
}
}
private static class Account {
private static Lock lock=new ReentrantLock();
public static Condition newDeposit=lock.newCondition();//------
private int balance = 0;
public int getBalance() {
return balance;
}
public void withDraw(int amount){
lock.lock();//------
try{
while(balance<amount){//------此处用while ,不能用if 原因:P332
System.out.println("\t\t\twait for a depodit");
newDeposit.await();
}
balance-=amount;
System.out.println("\t\t\tWithdraw " + amount +"\t\t" + getBalance());
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
finally {
lock.unlock();//------
}
}
public void deposit(int amount) {//cun kuan
lock.lock();
try {
balance += amount;
System.out.println("Deposit " + amount +"\t\t\t\t\t" + getBalance());
newDeposit.signalAll();//------
}
finally{
lock.unlock();
}
}
}
}
例2:示例学习:生产者/消费者
P334……
Java5之前,对象的内置监视器实现线程通信:对象上的wait(),notify(),notifyAll()方法类似于条件上的await(),signal(),signalAll()方法
(8)阻塞队列: