System.out.println(i++);
}
}
}
线程阻塞(join方式)
在一个线程里面持有另一个线程对象,调用对方的join方法,就会让当前线程处于等待,一直等到对方线程运行结束,才开始当前线程的运行。
线程状态
初始化------可运行---------------运行-------------结束
处在运行状态的线程可以进入阻塞,当阻塞解除的时候进入可运行状态,阻塞有两种方式:
不精确的方式是sleep,还有一种调用另一个线程对象的join方法,当另一个线程执行完,再解除当前线程的阻塞。
线程的同步
线程的同步:
什么叫多线程?
同时对一个资源操作会有什么问题?
多个线程操作同一个临界资源可能会出现访问冲突或者临界值不符合预期要求的情况,这个时候
我们可以使用synchronized块对其进行包围。
注意里面的参数是一个对象。
有两种方式:
1.synchronized(lock)
publicvoiddeposit(doublecount)throwsInterruptedException{
System.out.println("存入的金额:
"+count);
synchronized(lock){
doublenow=balance+count;
Thread.sleep(100);//存钱操作用时0.1秒钟
balance=now;
}
System.out.println("存入后金额:
"+balance);
}
publicvoidwithdraw(doublecount)throwsInterruptedException{
System.out.println("取出金额:
"+count);
synchronized(lock){
doublenow=balance-count;
Thread.sleep(200);//取钱操作用时0.2秒钟
balance=now;
}
System.out.println("取出后金额:
"+balance);
}
2.在方法前面直接加上synchronized
publicsynchronizedvoiddeposit(doublecount)throwsInterruptedException{
System.out.println("存入的金额:
"+count);
doublenow=balance+count;
Thread.sleep(100);//存钱操作用时0.1秒钟
balance=now;
System.out.println("存入后金额:
"+balance);
}
publicsynchronizedvoidwithdraw(doublecount)throwsInterruptedException{
System.out.println("取出金额:
"+count);
doublenow=balance-count;
Thread.sleep(200);//取钱操作用时0.2秒钟
balance=now;
System.out.println("取出后金额:
"+balance);
}
注意,如果多个线程出现需要使用多个锁的情况,需要在任何方法中保持锁的顺序一致。
才不至于出现死锁。
publicvoiddeposit(doublecount)throwsInterruptedException{
System.out.println("存入的金额:
"+count);
synchronized(lock1){
doublenow=balance+count;
Thread.sleep(100);//存钱操作用时0.1秒钟
synchronized(lock2){
balance=now;
System.out.println("存入后金额:
"+balance);
}
}
}
publicvoidwithdraw(doublecount)throwsInterruptedException{
System.out.println("取出金额:
"+count);
synchronized(lock1){
doublenow=balance-count;
Thread.sleep(200);//取钱操作用时0.2秒钟
synchronized(lock2){
balance=now;
System.out.println("取出后金额:
"+balance);
}
}
}
Object的wait,notify和notifyAll
#调用obj的wait(),notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj){...}代码段内。
#调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj){...}代码段内唤醒A。
#当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。
#如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。
java新特性之concurrentThread处理多线程问题
●摒弃synchronized
▪java.util.concurrent.locks.LOCK
✓lock()
✓unlock()
✓tryLock()
●摒弃wait()notify()notifyAll()
▪java.util.concurrent.locks.Condition
✓awaite()
✓signal()
signalAll()
线程之间进行合作用到锁的wait和notifyAll
packagecom.wdp;
publicclassCard{
privateObjectlock=newObject();
privatedoublebalance;
publicdoublegetBalance(){
returnbalance;
}
publicvoidsetBalance(doublebalance){
this.balance=balance;
}
/**
*withdraw
*/
publicvoidwithdraw(doublemoney){
while(true)
{
synchronized(this)
{
System.out.println("当前用户取款金额是:
"+money);
doublenow=balance-money;
try{
Thread.sleep(100);
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
while(this.balance-money<0){
try{
this.wait();
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
this.setBalance(this.balance-money);
System.out.println("取款后的余额是:
"+this.balance);
this.notifyAll();//通知所有在this上等待的线程可以开始执行
}//syn
}//while
}
/**
*deposit
*/
publicvoiddeposit(doublemoney){
while(true)
{
synchronized(this){
System.out.println("当前用户存款金额是:
"+money);
try{
Thread.sleep(100);
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
//判断如果now大于2000,在这里等待,等到this.banlance+100
while(this.balance+money>2000){
try{
this.wait();
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
this.setBalance(this.balance+money);
System.out.println("存款后的余额是:
"+this.balance);
this.notifyAll();
}//synchr
}//while
}
}
/**
*存款线程
*/
classDepositThreadextendsThread{
privateCardcard;
publicDepositThread(Cardcard){
this.card=card;
}
@Override
publicvoidrun(){
//TODOAuto-generatedmethodstub
card.deposit(100);
}
}
/**
取款线程
*/
classWithdrawThreadextendsThread{
privateCardcard;
publicWithdrawThread(Cardcard){
this.card=card;
}
@Override
publicvoidrun(){
//TODOAuto-generatedmethodstub
card.withdraw(50);
}
}
实例代码:
考虑一道淘宝的笔试题:
一个长度的30000的int数组,其中放随机数,利用多核的优势,求数组中元素的和。
TestArray.java
packagecom.exer;
importjava.util.Random;
importjava.util.concurrent.ExecutionException;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
importjava.util.concurrent.Future;
publicclassTestBigArray{
/*
*一个长度的30000的int数组,其中放随机数,利用多核的优势,求数组中元素的和。
*/
publicstaticvoidmain(String[]args)throwsInterruptedException,ExecutionException{
//TODOAuto-generatedmethodstub
longtotal=0;//存储综合
//1.创建数组,赋值随机数
int[]big=newint[30000000];
Randomr=newRandom();
for(inti=0;i<30000000;i++){
big[i]=r.nextInt(100);
}
//2.计算大数组元素的和
ExecutorServicepool=Executors.newCachedThreadPool();
for(inti=0;i<6;i++)
{
intstart=i*5000000;
intend=(i+1)*5000000;
SumThreadtask=newSumThread(big,start,end);
Futuref=pool.submit(task);
longpart=f.get();
total+=part;
}
System.out.println("total:
"+total);
}
}
SumThread.java
packagecom.exer;
importjava.util.concurrent.Callable;
publicclassSumThreadimplementsCallable{
privateint[]big;
privateintstart;
privateintend;
publicSumThread(int[]big,intstart,intend){
this.big=big;
this.start=start;
this.end=end;
}
@Override
publicLongcall()throwsException{
//TODOAuto-generatedmethodstub
longsum=0;
for(inti=start;isum+=big[i];
}
returnsum;
}
}