1.用两种方式实现两个线程,一个线程负责打印1-2600,另一个线程打印A-Z,反复打印10
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1.用两种方式实现两个线程,一个线程负责打印1-2600,另一个线程打印A-Z,反复打印10相关的知识,希望对你有一定的参考价值。
1.用两种方式实现两个线程,一个线程负责打印1-2600,另一个线程打印A-Z,反复打印100遍
2.实现两个线程,一个线程打印1-52,另一个线程打印A-Z,要求输出的结果: 1 2 A 3 4 B 5 6 C 7 8 D 9 10 11 12 ... 52 E F G H I J K ... X Y Z
3.利用线程的通信机制,用两个线程打印以下的结果: 1 2 A 3 4 B 5 6 C 7 8 D ... 49 50 Y 51 52 Z
public class ThreadDemo
/*用两种方式实现两个线程,一个线程负责打印1-2600,另一个线程打印A-Z,反复打印100遍*/
public static void main(String[] args)
Task1 task1 = new Task1();
Task2 task2 = new Task2();
task1.start();
task2.start();
class Task1 extends Thread
public void run()
for(int a=0;a<100;a++)
for(int i=1;i<=2600;i++)
System.out.println(i);
class Task2 extends Thread
public void run()
for(int a=0;a<100;a++)
for(char i='A';i<='Z';i++)
System.out.println(i);
第二种方式,实现Runnable接口:
public class ThreadDemo2
public static void main(String[] args)
Thread t1 = new Thread(new Task3());
Thread t2 = new Thread(new Task4());
t1.start();
t2.start();
class Task3 implements Runnable
public void run()
for(int a=0;a<100;a++)
for(int i=1;i<=2600;i++)
System.out.println(i);
class Task4 implements Runnable
public void run()
for(int a=0;a<100;a++)
for(char i='A';i<='Z';i++)
System.out.println(i);
2:用多线程加锁: 参考技术A 先找到数字和字母的规律再说,这个规律我可没看出来 参考技术B 你先要告诉大家,你想用什么语言实现啊!
Java多线程带你用不一样的思维看创建线程的两种方式
文章目录
创建线程的两种方式
通过实现 Runnable 接口
public class CreateThread
// 继承 Thread 类来
static class MyThread extends Thread
@Override
public void run()
System.out.println("Hello MyThread");
// 实现 Runnable 接口:这个方式更灵活,因为实现接口后,可以继承其他类
static class MyRun implements Runnable
@Override
public void run()
System.out.println("Hello MyRun");
public static void main(String[] args)
new MyThread().start();
new Thread(new MyRun()).start();
new Thread(()->
System.out.println("hello lambda!");
).start();
上面是主流的创建线程的两种方法,那么我们看一下这两种方法有什么区别吧
Runnable:可以看到使用 Runnable 来创建线程,使用 Runnable 接口引向一个匿名内部类,该内部类重写了 Runnable 接口的run方法,再次之后,仍需要创建一个新的线程,然后传入 runnable ;
Thread : 直接继承 Thread 然后重写 run 方法
从面对对象的角度来思考:
两种方法都是为了构造一个 Thread 类,大家可以看到实现了 runnable 接口后,仍然是创建了一个新的线程,把接口作为 Thread 的构造方法参数传入
public Thread(Runnable target)
init(null, target, "Thread-" + nextThreadNum(), 0);
start 和 run 方法解析
在初次使用的时候,大家很容易看见,我们重写的是 run 方法,那么为什么调用的时候,调用的却是 start 方法
start启动新线程:通知JVM,有空闲就创建新线程,何时创建由线程调度器控制(并非调用start方法就会创建,即两个调用start的方法顺序不代表线程的创建顺序)
调用完start后,在主线程中启动
public synchronized void start()
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try
start0();
started = true;
finally
try
if (!started)
group.threadStartFailed(this);
catch (Throwable ignore)
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
为什么不能调用 run 方法 调用了会发生什么事情
public static void main(String[] args)
Runnable runnable = ()->
System.out.println(Thread.currentThread().getName());
;
runnable.run();
new Thread(runnable).start();
main:因为在调用的时候,我们使用的是接口.方法,实际上 runnable 接口指向一个匿名内部类,这个类重写了 run 方法,我们在调用的时候,调用的是普通方法 run ,并且是在主函数里面调用的 主线程就是 main
Thread-0 :
重复调用 start 方法会发生什么事情
Exception in thread “main” java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:708)
at StartTwice.main(StartTwice.java:5)
为什么不能重复调用
原因:一旦开始线程完毕,会进入终止状态,无法回退
if (threadStatus != 0)
throw new IllegalThreadStateException();
threadStatus:
Java 线程状态,已初始化以指示线程“尚未启动”
彩蛋:同时用两种方法来实现同一个线程,会遇到什么
大家可能没有考虑过,如果new Thread 类,并且传入一个 runnable 重写 runnable 接口的 run 方法的同时,重写Thread 类的 run 方法会发生什么事情
public static void main(String[] args)
new Thread(new Runnable()
//匿名内部类
@Override
public void run()
System.out.println("Runnable");
)
//重写
@Override
public void run()
System.out.println("Thread");
.start();
从面向对象的思想去考虑:
刚才使用的匿名内部类,然后重写了Thread,
两种,一种是重写run方法,一种是给run传入target
我们看看源码,才能知道为什么调用的是 Thread 类的 run
如果该线程是使用单独的 unnable 运行对象构造的,则调用该 Runnable 对象的run 方法;否则,此方法不执行任何操作并返回。 Thread 的子类应覆盖此方法。
private Runnable target;
@Override
public void run()
if (target != null)
target.run();
解释一下 targer 是我们使用 runnable 方法来构建Thread 类时传入的参数。
这个三行代码是什么,大家思考一下,这个是 Thread 类的 run 方法,我们平时使用的新建 Thread 创建线程,就会重写这个方法,即这个三行代码是被重写的,不会调用。但是如果仅仅只是 runnable 新建线程,我们只是重写了 Runnable 接口的 run 方法,启动线程 Thread 调用的就是未被重写的 这三行Thread 类的run方法中的语句。但两者都有时,Thread 的 run 方法就会被前者覆盖,上方的 run 方法中三行代码永远不会执行
小知识:调用start方法,线程就会立刻启动吗?
- 调用了 start 方法,线程就立刻启动了吗???
在调用 start 方法后,其实先通知JVM,让其有空闲就创建新线程,但是何时真正创建由线程调度器决定。即,在某些情况下,可能会出现先 start 的线程后执行
以上是关于1.用两种方式实现两个线程,一个线程负责打印1-2600,另一个线程打印A-Z,反复打印10的主要内容,如果未能解决你的问题,请参考以下文章