什么是并发
- 并发是程序同时处理多个任务的能力
- 并发编程的根源是在于对多任务情况下对访问自由的有效控制
基本概念
进程
- 进程进程之间是相互隔离的,互不干扰
- 计算机资源分配的基本单位
线程
- 线程是进程内的一个基本任务,每个线程都有自己的功能
- 是CPU调度的基本单位
并行
- 多核CPU
- 两个任务同时执行的
并发
- 单核CPU的时间片轮转
同步
异步
- 无需等待,等处理完毕之后通知
临界区
- 表示可以被多个线程访问的共享资源
- 同一时间之内有一个线程访问临界区
死锁
- 多个进程争夺临界资源造成的互相僵持的状态
饥饿
- 饥饿指的是某一线程或多个线程因为某些原因一直获取不到资源
活锁
- 资源没有被占用、多个线程还都在等待
线程安全
- 在拥有共享数据的多条线程并行执行的程序中,各个线程都可以争取的执行,不会出现数据污染的情况
Java内存模型
创建线程方式
继承Thread类创建线程
public class Match1 {
public static void main(String[] args) {
Runner runner1 = new Runner();
runner1.setName("跑者A");
Runner runner2 = new Runner();
runner2.setName("跑者B");
runner1.start();
runner2.start();
}
}
class Runner extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(this.getName() + i);
}
}
}
几个进程:
- 四个,X、Y、主进程、垃圾回收进程
实现Runnable接口创建线程
public class Match1 {
public static void main(String[] args) {
Thread thread1 = new Thread(new Runner());
thread1.setName("跑者A");
Thread thread2 = new Thread(new Runner());
thread2.setName("跑者B");
thread1.start();
thread2.start();
}
}
class Runner implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "跑了" + i + "米");
}
}
}
实现Callable接口
public class Match1 {
public static void main(String[] args) {
Runner runner1 = new Runner();
runner1.setName("跑者1");
Runner runner2 = new Runner();
runner2.setName("跑者2");
ExecutorService executorService = Executors.newFixedThreadPool(2);
Future<Integer> result1 = executorService.submit(runner1);
Future<Integer> result2 = executorService.submit(runner2);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
executorService.shutdown();
}
}
class Runner implements Callable<Integer> {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public Integer call() {
for (int i = 0; i < 100; i++) {
System.out.println(this.getName() + "跑了" + i + "米");
}
return null;
}
}
优缺点
继承Thread | 实现Runnable | 利用线程池 | |
---|---|---|---|
优点 | 编程简单,执行效率高 | 面向接口编程,破除单继承的影响;执行效率高 | 容器管理线程;允许返回值和异常 |
缺点 | 单继承限制,无法有效对线程组控制 | 无法有效控制线程组;无异常和返回值 | 执行效率低,编程麻烦 |
使用场景 | 不推荐 | 简单的多线程 | 企业级应用 |
Synchronized线程同步机制
测试StringBuilder和StringBuffer线程安全
// StringBuffer是线程安全的
public class Main {
public static void main(String[] args) throws InterruptedException {
StringBuffer stringBuffer = new StringBuffer();
StringTest stringTest = new StringTest();
stringTest.setStringBuffer(stringBuffer);
Thread t1 = new Thread(stringTest);
Thread t2 = new Thread(stringTest);
t1.start();
t2.start();
Thread.sleep(100);
System.out.println(stringTest.getStringBuffer().length());
}
}
class StringTest implements Runnable {
private StringBuffer stringBuffer;
public StringBuffer getStringBuffer() {
return stringBuffer;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
stringBuffer.append('a');
}
}
public void setStringBuffer(StringBuffer stringBuffer) {
this.stringBuffer = stringBuffer;
}
}
//StringBuilder是线程不安全的
public class Main {
public static void main(String[] args) throws InterruptedException {
StringBuilder stringBuilder = new StringBuilder();
StringTest stringTest = new StringTest();
stringTest.setStringBuilder(stringBuilder);
Thread t1 = new Thread(stringTest);
Thread t2 = new Thread(stringTest);
t1.start();
t2.start();
Thread.sleep(1000);
System.out.println(stringTest.getStringBuilder().length());
}
}
class StringTest implements Runnable {
private StringBuilder stringBuilder;
public StringBuilder getStringBuilder() {
return stringBuilder;
}
public void setStringBuilder(StringBuilder stringBuilder) {
this.stringBuilder = stringBuilder;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
stringBuilder.append('a');
}
}
}
此处评论已关闭