线程并发与并行
1.并发:
当多线程共同使用一个CPU或只有一个CPU可用的时候,这个CPU同一时刻只能执行一个线程,所以这时候CPU会分割为多个时间段,将多个线程快速轮换。
2.并行
同一时刻,可以执行多个线程,例如读取多个磁盘文件,并行代表同一时刻,同时开启多个线程处理多个文件。
并发与并行都是由系统操控的,当系统只有一个CPU资源可用的时候,这些线程就会抢占资源,并发执行,轮流开启,当系统CPU资源空余的时候,就会并行执行,合理利用CPU资源。
Callable:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class TestCallable {
public static void main(String[] args) {
ThreadDemo td = new ThreadDemo();
FutureTask<Integer> result = new FutureTask<>(td);
new Thread(result).start();
try {
Integer sum = result.get();
System.out.println(sum);
System.out.println("------------------------------------");
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
class ThreadDemo implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i <= 100000; i++) {
sum += i;
}
return sum;
}
}
Callable和Runnble的区别:
1)Callable有返回值,Runnble无返回值。
2)Runnable可以作为Thread构造器的参数,通过开启新的线程来执行,也可以通过线程池来执行。而Callable只能通过线程池执行
线程同步通行
当多个线程共享相同的任务,并行执行并都有可能修改数据,但是当一些数据被一个线程占用的时候,另一个线程再调用并想修改时,可能会访问一个无效值,所以为了防止线程访问到无效值,我们可以给线程加锁,例如利用synchronized声明这些方法,当有其他线程在执行都有synchronized的声明方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。
public synchronized void setTest(int i){
this.i = i;
}
如上面方法,当有线程访问的时候,就会检查有没其他线程在调用,有则进行进入等待状态,直到其他线程调用完毕。