第1关:并发编程的三个概念
任务描述
在我们进行应用开发的时候,常常会关注网站的并发,如果网站的用户量很多,当这些用户同时访问一个服务的时候,我们的服务器就会接收到大量的并发请求,处理好这些并发请求是一个合格程序员必须要完成的工作。
理解并发编程的三个概念对于我们更好的开发高并发的
Web
应用有很大的帮助。
本关的任务就是理解并发编程的三个重要概念并完成右侧选择题。
-
1、在并发编程中,我们需要以下哪几个特性来保持多线程程序执行正确(ABD )
A、可见性
B、原子性
C、并发性
D、有序性 -
2、请分析以下语句哪些是原子操作(AB )
A、int a = 3;
B、boolean flag = false;
C、a–;
D、a =a *a -
3、以下代码的执行结果是(E)
-
public class Test {
-
public int inc = 0;
-
public void increase() {
-
inc++;
-
}
-
public static void main(String[] args) {
-
final Test test = new Test();
-
for(int i=0;i<10;i++){
-
new Thread(){
-
public void run() {
-
for(int j=0;j<1000;j++)
-
test.increase();
-
};
-
}.start();
-
}
-
while(Thread.activeCount()>1) //保证前面的线程都执行完
-
Thread.yield();
-
System.out.println(test.inc);
-
}
-
}
A、10000
B、9870
C、大于10000
D、小于10000
E、不一定,大概率小于一万 -
第2关:使用synchronized关键字同步线程
任务描述
本关任务:使右侧代码中的
insert
方法在同一时刻只有一个线程能访问。
编程要求
请仔细阅读右侧代码,根据方法内的提示,在
Begin - End
区域内进行代码补充,具体任务如下:
-
使
num
变量在同一时刻只能有一个线程可以访问。
测试说明
使程序的输出结果如下:
通关代码
package step2;
public class Task {
public static void main(String[] args) {
final insertData insert = new insertData();
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
public void run() {
insert.insert(Thread.currentThread());
}
}).start();
}
}
}
class insertData{
public static int num =0;
/********* Begin *********/
public synchronized void insert(Thread thread){
for (int i = 0; i <= 5; i++) {
num++;
System.out.println(num);
}
}
/********* End *********/
}
第3关:使用线程锁(Lock)实现线程同步
任务描述
本关任务:使用
Lock
,实现对于某一块代码的互斥访问
编程要求
请仔细阅读右侧代码,根据方法内的提示,在
Begin - End
区域内进行代码补充。 ####测试说明
使得程序输出如下结果(因为线程的执行顺序是随机的可能需要你评测多次):
通关代码
package step3;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Task {
public static void main(String[] args) {
final Insert insert = new Insert();
Thread t1 = new Thread(new Runnable() {
public void run() {
insert.insert(Thread.currentThread());
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
insert.insert(Thread.currentThread());
}
});
Thread t3 = new Thread(new Runnable() {
public void run() {
insert.insert(Thread.currentThread());
}
});
// 设置线程优先级
t1.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(Thread.NORM_PRIORITY);
t3.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
t3.start();
}
}
class Insert {
public static int num;
// 在这里定义Lock
private Lock lock = new ReentrantLock();
public void insert(Thread thread) {
/********* Begin *********/
if(lock.tryLock()){
try{
System.out.println(thread.getName()+"得到了锁");
for (int i = 0; i < 5; i++) {
num++;
System.out.println(num);
}
}finally{
System.out.println(thread.getName()+"释放了锁");
lock.unlock();
}
}else{
System.out.println(thread.getName()+"获取锁失败");
}
}
/********* End *********/
}
在这种情况之下,程序输出所需要的结果可能需要多次,因为线程的执行顺序是随机的,我们可以通过sleep()方法来改进程序,这样就不需要设置线程优先级。
通关代码(改进)
package step3;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Task {
public static void main(String[] args) throws InterruptedException {
final Insert insert = new Insert();
Thread t1 = new Thread(new Runnable() {
public void run() {
insert.insert(Thread.currentThread());
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
insert.insert(Thread.currentThread());
}
});
Thread t3 = new Thread(new Runnable() {
public void run() {
insert.insert(Thread.currentThread());
}
});
// 设置线程优先级
/*
t1.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(Thread.NORM_PRIORITY);
t3.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
t3.start();
*/
t1.start();
t2.sleep(500);
t2.start();
t3.sleep(1000);
t3.start();
}
}
class Insert {
public static int num;
// 在这里定义Lock
private Lock lock = new ReentrantLock();
public void insert(Thread thread) {
/********* Begin *********/
if (lock.tryLock()) {
try {
System.out.println(thread.getName() + "得到了锁");
for (int i = 0; i < 5; i++) {
num++;
System.out.println(num);
}
} finally {
System.out.println(thread.getName() + "释放了锁");
lock.unlock();
}
} else {
System.out.println(thread.getName() + "获取锁失败");
}
}
/********* End *********/
}
第4关:使用volatile实现变量的可见性
任务描述
本关任务:使用
volatile
关键字与同步实现右侧程序输出
10000
。
编程要求
请仔细阅读右侧代码,根据方法内的提示,在
Begin - End
区域内进行代码补充。 ####测试说明
预期输出:
10000
。
提示:可以使用两种方式实现原子性,所以本关有多种方式都可以通关。
通关代码
package step4;
public class Task {
public volatile int inc = 0;
//请在此添加实现代码
/********** Begin **********/
public synchronized void increase() {
inc++;
}
/********** End **********/
public static void main(String[] args) {
final Task test = new Task();
for (int i = 0; i < 10; i++) {
new Thread() {
public void run() {
for (int j = 0; j < 1000; j++)
test.increase();
};
}.start();
}
while (Thread.activeCount() > 1) // 保证前面的线程都执行完
Thread.yield();
System.out.println(test.inc);
}
}