题目一
(一)采用2种方法实现:创建2个线程,第一个线程计算1+2+…+10000的值,第二个线程计算10!的值。在主类的main方法中输出2个线程的计算结果。
1)源程序(采用继承Thread类的方法):
public class ThreadTest01 {
public static void main(String[] args) {
MyThread1 t1 = new MyThread1();
MyThread2 t2 = new MyThread2();
t1.start();
t2.start();
while (t1.getAlive() || t2.getAlive()){
}
System.out.println("1+2+......+10000=" + t1.getSum());
System.out.println("10!=" + t2.getSum());
}
}
class MyThread1 extends Thread {
private int sum = 0;
private int i = 1;
private boolean alive = true;
@Override
public void run() {
while (i<=10000){
sum+=i;
i++;
}
alive = false;
}
public int getSum() {
return this.sum;
}
public boolean getAlive(){
return alive;
}
}
class MyThread2 extends Thread {
private int sum = 1;
private boolean alive = true;
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
sum *= i;
}
alive = false;
}
public int getSum(){
return this.sum;
}
public boolean getAlive(){
return alive;
}
}
运行结果截图:
2)源程序(采用实现Runnable接口的方法): :
public class ThreadTest02 {
public static void main(String[] args) {
MyThread3 myThread1 = new MyThread3();
MyThread4 myThread2 = new MyThread4();
Thread t3 = new Thread(myThread1);
Thread t4 = new Thread(myThread2);
t3.start();
t4.start();
while (myThread1.getAlive() || myThread2.getAlive()) {
}
System.out.println("1+2+......+10000=" + myThread1.getSum());
System.out.println("10!=" + myThread2.getSum());
}
}
class MyThread3 implements Runnable {
private int sum = 0;
private int i = 1;
private boolean alive = true;
@Override
public void run() {
while (i <= 10000) {
sum += i;
i++;
}
alive = false;
}
public int getSum() {
return this.sum;
}
public boolean getAlive() {
return alive;
}
}
class MyThread4 implements Runnable {
private int sum = 1;
private boolean alive = true;
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
sum *= i;
}
alive = false;
}
public int getSum() {
return this.sum;
}
public boolean getAlive() {
return alive;
}
}
运行结果截图:
题目二
(二)现有三个线程t1,t2,t3,保证t1运行结束后t2运行,t2运行结束后t3运行。编程测试。
源程序:
public class ThreadTest03 {
public static void main(String[] args) {
MyThread5 t1 = new MyThread5("t1");
MyThread5 t2 = new MyThread5("t2");
MyThread5 t3 = new MyThread5("t3");
try {
t1.start();
t1.join();
t2.start();
t2.join();
t3.start();
t3.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyThread5 extends Thread {
private int j = 1;
public MyThread5(String name) {
this.setName(name);
}
@Override
public void run() {
for (int i = 1; i < 5; i++) {
System.out.println("线程" + Thread.currentThread().getName() + "执行完毕--->" + j++);
}
}
}
题目三
(三)编程模拟“生产者-消费者”问题。(参考教材上在P138页程序)
生产者:生产字符a,b,c…z
消费者:消费字符a,b,c…z
要求:生产者生产一个字符,消费者就消费一个字符,仓库中只能存储一个字符。
源程序:
import java.util.ArrayList;
import java.util.List;
public class ThreadTest04 {
public static void main(String[] args) {
List list = new ArrayList();
Thread t1 = new Thread(new Producer(list));
Thread t2 = new Thread(new Consumer(list));
t1.setName("生产者线程");
t2.setName("消费者线程");
t1.start();
t2.start();
}
}
class Producer implements Runnable {
private String chars = "abcdefghijklmnopqrstuvwxyz";
private List list;
public Producer(List list) {
this.list = list;
}
@Override
public void run() {
while (true) {
synchronized (list) {
if (list.size() > 0) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
char c = chars.charAt((int) (Math.random() * 26));
list.add(c);
System.out.println(Thread.currentThread().getName() + "--->" + c);
list.notifyAll();
}
}
}
}
class Consumer implements Runnable {
private List list;
public Consumer(List list) {
this.list = list;
}
@Override
public void run() {
while (true) {
synchronized (list) {
if (list.size() == 0) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Object c = list.remove(0);
System.out.println(Thread.currentThread().getName() + "--->" + c);
list.notifyAll();
}
}
}
}
运行结果截图:
实验小结:
1、 实现多线程的方法有两种:1)直接继承Thread重写run方法 2)实现Runnable重写run方法(还可以用匿名内部类的方式来实现)。
2、 启动一个线程,就是是调用线程对象的start()方法。而不是run() 方法,run()方法不是启动线程,而是调用了一个方法而已。
3、 线程相关:
1)获取当前线程对象?
Thread t = Thread.currentThread();
2)获取线程对象的名字
String name = 线程对象.getName();
3)修改线程对象的名字
线程对象.setName(“线程名字”);
4)线程默认的名字:
Thread-0
Thread-1
…
4、 线程的sleep方法(static方法,参数为ms),让当前线程进入休眠,也就是进入”阻塞状态”,放弃所占有的CPU时间片,让给其他线程来使用。
5、 yield()方法,作用:让位,当前线程暂停,回到就绪状态,让给其它线程。
6、 join()方法, 合并到当前线程中,当前线程受阻塞,t线程执行直到结束。