多线程练习题
1.写一段简单的程序,启动两个线程交替打印1–100
题目分析:
只打印1—100,为了保证数据的同步必须加锁,同时又需要线程交替打印,则需要线程间的通信。
解题思想:
启动两个线程A和线程B,两个线程交替打印,首先A打印,打印完,wait,释放对象锁,此时B获得对象锁,打印,且唤醒A,然后B wait ,反复执行。
代码:
/**
* 两个线程交替输出1--100
* @auther plg
* @date 2019/5/12 22:05
*/
public class Print implements Runnable {
private int num = 1;
@Override
public void run() {
while(true){
synchronized (this){
this.notify();
if(num <= 100){
System.out.println(Thread.currentThread().getName() + " == " + num);
num++;
}else{
break;
}
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Print print = new Print();
Thread thread1 = new Thread(print,"A");
Thread thread2 = new Thread(print,"B");
thread1.start();
thread2.start();
}
}
执行结果:
2.写一段简单的程序,启动N个线程交替打印0----100
启动N个线程,首先根据线程ID判断是否轮到该线程打印,如果是打印,且唤醒其它线程,如果不是则wait就好了。
package com.github;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @auther plg
* @date 2019/5/13 20:54
*/
public class TestN extends Thread {
private static int num = 0;
private static int count = 0;
private int id = 0;
public TestN(int id,String name) {
super(name);
this.id = id;
}
@Override
public void run() {
synchronized (TestN.class){
while(true){
while(num % count != this.id){
if(num > 100){
break;
}
try {
TestN.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(num > 100){
break;
}
System.out.println(Thread.currentThread().getName() + " " + num);
num++;
TestN.class.notifyAll();
}
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入:");
count = input.nextInt();
for(int i = 0; i < count; i++){
new TestN(i,"thread-" + i).start();
}
}
}
运行结果:
3.写一段简单的程序,启动N个线程对一个大数组求和,将所得结果到主线程汇总并输出。
解题思想:
将大数组按照线程的数量进行分组,每个线程只对自己负责的组进行求和,最终在主线程进行汇总。
代码实现:
- 生成一个目标数组
// for test 随机生成大小为size,[0 , max]的数组
public static int[] genergte(int max,int size){
int[] arr = new int[size];
for(int i = 0; i < size; i++){
arr[i] = (int)((Math.random()) * (max + 1));
}
return arr;
}
- 测试代码(将通过遍历求得的和与通过并行求得的和进行比较,相等则正确,不相等则错误)
public static int getSum(){
int sum = 0;
for(int i = 0; i < arr.length; i++){
sum += arr[i];
}
return sum;
}
public static void isRight(int sum){
System.out.println("线程所求: " + sum + " 遍历所求: " + getSum() + " 结果: " + (sum == getSum() ? "Nice" : "Error"));
}
- 实现Callable接口后的call方法简单的求和逻辑
@Override
public Integer call() throws Exception {
int sum = 0;
for(int i = start; i < end; i++){
sum += arr[i];
}
return sum;
}
- 总体代码:
package com.github.excellent01;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.*;
/**
* 多线程对数组求和
* @auther plg
* @date 2019/5/14 17:07
*/
public class GetSum implements Callable<Integer> {
private int start = 0;
private int end = 0;
// 数组共享,需加static修饰
private static int[] arr = null;
static {
arr = genergte(1000,10000);
}
public GetSum(int start, int end) {
this.start = start;
this.end = end;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for(int i = start; i < end; i++){
sum += arr[i];
}
return sum;
}
public static int getSum(){
int sum = 0;
for(int i = 0; i < arr.length; i++){
sum += arr[i];
}
return sum;
}
public static void isRight(int sum){
System.out.println("线程所求: " + sum + " 遍历所求: " + getSum() + " 结果: " + (sum == getSum() ? "Nice" : "Error"));
}
// for test 随机生成大小为size,[0 , max]的数组
public static int[] genergte(int max,int size){
int[] arr = new int[size];
for(int i = 0; i < size; i++){
arr[i] = (int)((Math.random()) * (max + 1));
}
return arr;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
Scanner in = new Scanner(System.in);
System.out.print("请输入线程数量:");
int threadCount = 0;
threadCount = in.nextInt();
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
// 对数组进行分组
int subArrSize = (arr.length / threadCount) + 1;
List<Future<Integer>> list = new ArrayList<>();
int sum = 0;
for(int i = 0; i < arr.length; i += subArrSize){
int end = i + subArrSize;
end = end >= arr.length ? arr.length : end;
int num = end;
list.add(executorService.submit(new GetSum(i,end)));
}
// 汇总
for(Future<Integer> future : list){
sum += future.get();
}
//判断结果
isRight(sum);
}
}
- 运行结果:(多次执行均是对的)。
4…写一段简单的程序,实现并行搜素。
给定一个无序大数组,在数组中查找某个值,找到返回该值的下标,找不到返回-1.
对于串行来说,仅需要遍历一遍数组即可,但采用并行的方式,就需要一些额外的通信机制,使得各个线程有效的运行。
解题思想,将整个大数组按照线程的个数,分为若干组,每个线程在自己的组内查找,找到就返回结果。