目录
问题:实现两个吸纳成交替打印1-100
Thread方式创建线程
Thread方式适合初学者。步骤如下:
- 首先定义一个类MyThread01,继承Thread类,然后重写run()方法;
- 同理创建MyThread02;
- 创建测试类
MyThread01 类
public class MyThread01 extends Thread {
MyObject obj;
public MyThread01(MyObject obj) {
this.obj = obj;
}
@Override
public void run() {
while (obj.i<=98) {
synchronized (obj){
if (obj.flag){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"\t"+(++obj.i));
obj.flag=true;
obj.notify();
}
}
}
}
MyThread02 类
public class MyThread02 extends Thread {
MyObject obj;
public MyThread02(MyObject obj) {
this.obj = obj;
}
@Override
public void run() {
while (obj.i<=98) {
synchronized (obj){
if (!obj.flag){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"\t"+(++obj.i));
obj.flag=false;
obj.notify();
}
}
}
}
测试类:MyThread传递的参数必须相同才能实现交替打印
public class Test02 {
public static void main(String[] args) {
MyObject obj = new MyObject();
new MyThread01(obj).start();
new MyThread02(obj).start();
}
}
Runnable方式创建线程
有的人可能会觉得Runnable方式有点多余,已经有了Thread方式,为什么还要这种创建方式呢?我们都知道,Java的继承是单继承,如果我们继承了一个类,就不能在继承其他类。有时候我们创建的类必须要继承某个类,又要用线程,这个时候使用Thread方式创建线程已经不能满足需求了。用Runnable方式正好可以解决这个问题。因为在Java中可以实现多个接口。
第一步:定义一个变量类,用作synchronized的变量
public class Alter {
public int i=1;
public boolean flag;
}
第二部:创建第一个线程 Thread-0
public class Alternate implements Runnable {
private Alter alter;
public Alternate(Alter alter) {
this.alter = alter;
}
@Override
public void run() {
while (true){
synchronized (alter){
if (alter.i<100) {
if (alter.flag){
try {
alter.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"\t"+(alter.i++));
alter.flag=true;
alter.notify();
}
}
}
}
}
第三步:创建第二个线程 Thread-1
public class Alternate01 implements Runnable {
private Alter alter;
public Alternate01(Alter alter) {
this.alter = alter;
}
@Override
public void run() {
while (true){
synchronized (alter){
if (alter.i<=100) {
if (!alter.flag){
try {
alter.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"\t"+(alter.i++));
alter.flag=false;
alter.notify();
}
}
}
}
}
第四步:创建测试类 。很明显,相比于Thread方式,Runnable方式创建线程多了实例化Runnable类对象的步骤
class AlternateTest {
public static void main(String[] args) {
Alter alter=new Alter();
Alternate a = new Alternate(alter);
Alternate01 a01 = new Alternate01(alter);
new Thread(a).start();
new Thread(a01).start();
}
}
内部类方式创建线程
这种创建方式显得直接了当,适合高手
第一种:在主函数外定义内部类
因为主函数是用static修饰的,所以这样方式创建的内部类也要用static修饰
public class AlternotePrint {
//定义内部类,用作synchronized的变量
static class MyObject{
boolean flag=false;
int i=1;
}
public static void main(String[] args) {
MyObject obj = new MyObject();
//使用匿名内部类的方式创建线程
new Thread(()->{
while (true) {
synchronized (obj){
if (obj.i<100) {
if (obj.flag){
try {
obj.wait();//该线程进入无限等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"\t"+obj.i);
obj.i++;
obj.flag=true;
obj.notify();//唤醒另一个线程
}
}
}
}).start();
new Thread(()->{
while (true) {
synchronized (obj){
if (obj.i<=100) {
if (!obj.flag){
try {
obj.wait();//该线程进入无限等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"\t"+obj.i);
obj.i++;
obj.flag=false;
obj.notify();//唤醒另一个线程
}
}
}
}).start();
}
}
第二种:在主函数内创建内部类
这种方式创建的内部类不许要用static修饰
public class Test03 {
public static void main(String[] args) {
//定义内部类
class MyObject{
boolean flag=false;
int i=0;
}
MyObject obj = new MyObject();
new Thread(()->{
while (obj.i<=98) {
synchronized (obj){
if (obj.flag){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"\t"+(++obj.i));
obj.flag=true;
obj.notify();
}
}
}).start();
new Thread(()->{
while (obj.i<=98) {
synchronized (obj){
if (!obj.flag){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"\t"+(++obj.i));
obj.flag=false;
obj.notify();
}
}
}).start();
}
}
Callable方式创建线程
不管是使用Thread、Runnable,还是内部类的方式创建线程,run()方法的返回值类型都是void,也就是没有返回值,那有时候我们需要返回值怎么办。其实Java中又一种创建线程的方式是又返回值的,那就是Callable 方式。
比如使用线程求1-100的偶数之和
使用之前的三种方式也能达到我们的这样的效果,但是这样是没有返回值的,我们只能在线程中求和并输出总和。
现在用Callable做一下:
第一步:创建MyCallable类实现Callable接口
import java.util.concurrent.Callable;
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() {
int sum=0;
for (int i = 1; i <= 100; i++) {
if (i%2==0){
sum+=i;
}
}
return sum;
}
}
第二步:测试类
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
class MyCallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<Integer> task = new FutureTask<>(new MyCallable());
new Thread(task).start();
Integer sum = task.get();//返回值
System.out.println(sum);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/14622.html