练习1
1. 用多线程代码来模拟,迅雷用3个线程下载100M资源的的过程。
每个线程每次,一次下载1兆(M)资源,直到下载完毕,即剩余的待下载资源大小为0
(用一个整数表示资源大小,每次个线程每次下载多少兆(M), 剩余待下载资源就减少多少兆(M),
模拟我们售票的代码实现,考虑多线程的数据安全问题)
public class Demo4 {
public static void main(String[] args) {
downLoad downLoad = new downLoad();
Thread t1 = new Thread(downLoad);
Thread t2 = new Thread(downLoad);
t1.setName("线程1");
t2.setName("线程2");
t1.start();
t2.start();
//Thread(Runnable target, String name)
new Thread(downLoad,"线程3").start();
}
}
class downLoad implements Runnable {
public int number = 100;
@Override
public void run() {
while (number > 0) {
//睡眠100毫秒
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//同步代码块synchronized
synchronized (this) {
if (number > 0) {
number--;
System.out.println(Thread.currentThread().getName() + "待下载资源为:" + number);
if (number==0){
System.out.println("资源下载完成!");
}
}
}
}
}
}
练习2
1. 创建2个线程,打印从0到99这100个数字,要求线程交叉顺序打印。
要求使用线程间通信实现。即我打印一个数字,你打印一个数字,两线程协作完成。
比如:
线程1: 0
线程2: 1
线程1: 2
线程2: 3
线程1: 4
线程2: 5片
class Number implements Runnable {
private int number = 1;
private Object obj = new Object();
@Override
public void run() {
while (true) {
//使用同步代码块(解决安全问题)
synchronized (this) {
//this代表的都是当前对象
this.notify();
if (number <= 100) {
System.out.println(Thread.currentThread().getName() + ":" + number);
number++;
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
}
}
}
public class PrintNumber {
public static void main(String[] args) {
Number number = new Number();
/*Thread t1 = new Thread(number);
Thread t2 = new Thread(number);
t1.setName("线程 1");
t2.setName("线程 2");
t1.start();
t2.start();*/
new Thread(number,"线程-1").start();
new Thread(number,"线程-2").start();
}
}
在这里插入代码片
//==================================================================0
public class Demo2 {
public static void main(String[] args) {
printNumber printNumber = new printNumber();
printOdd printOdd = new printOdd(printNumber);
printEven printEven = new printEven(printNumber);
Thread t1 = new Thread(printEven);
Thread t2 = new Thread(printOdd);
t1.setName("线程1");
t2.setName("线程2");
t1.start();
t2.start();
}
}
//==================================================================1
//类,封装被打印的数字
class printNumber {
private int i = 0;
//被打印数字增加1
public void add() {
i++;
}
//获取打印数字值
public int value() {
return i;
}
}
//==================================================================2
abstract class printTask implements Runnable {
//被打印数字
protected printNumber number1;
public printTask(printNumber number1) {
this.number1 = number1;
}
//抽象方法
protected abstract boolean shouldPrint();
@Override
public void run() {
//
while (number1.value() <= 99) {
synchronized (number1) {
if (99 < number1.value()) {
break;
}
if (!shouldPrint()) {
try {
//
number1.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println(Thread.currentThread().getName()
+ "----" + number1.value());
number1.add();
if (number1.value() > 99) {
System.out.println("打印结束");
}
//唤醒被wait()的进程
number1.notifyAll();
}
}
}
}
}
//================================================================================3
//打印偶数 使用方式一:继承
class printEven extends printTask {
public printEven(printNumber number1) {
super(number1);
}
//打印偶数的线程,当number对象中,i的值为偶数时才打印
@Override
protected boolean shouldPrint() {
return number1.value() % 2 == 0;
}
}
//================================================================================4
//打印奇数 使用方式一:继承
class printOdd extends printTask {
public printOdd(printNumber number1) {
super(number1);
}
//打印奇数的线程,当number对象中,i的值为奇数时才打印
@Override
protected boolean shouldPrint() {
return number1.value() % 2 != 0;
}
}