1.多线程是一种并发机制的有效手段。进程和线程一样,都是实现并发的一个基本单位。线程是比进程更小的一种实现单位,线程是在进程的基础上的进一步划分。所谓的多线就是在一个进程中产生了多个线程,这些线程可以同时存在,同时运行。
private
String
userName
;
public
String getUserName() {
return
userName
;
public
void
setUserName(String userName) {
this
.
userName
= userName;
public
ThreadDemo(String userName) {
this
.
userName
= userName;
@Override
public
void
run() {
for
(
int
i=1;i<10;i++){
System.
out
.println(
userName
+i);
public
static
void
main(String[] args) {
private
String
userName
;
public
String getUserName() {
return
userName
;
public
void
setUserName(String userName) {
this
.
userName
= userName;
public
ThreadDemo(String userName) {
this
.
userName
= userName;
@Override
public
void
run() {
for
(
int
i=1;i<10;i++){
public
static
void
main(String[] args) {
public
synchronized
void
start() {
/**
if
(
threadStatus
!= 0)
throw
new
IllegalThreadStateException();
/* Notify the group that this thread is about to be started
group
.add(
this
);
boolean
started =
false
;
try
{
try
{
if
(!started) {
group
.threadStartFailed(
this
);
/* do nothing. If start0 threw a Throwable then
private
native
void
start0();
private
String
userName
;
public
String getUserName() {
return
userName
;
public
void
setUserName(String userName) {
this
.
userName
= userName;
public
ThreadDemo(String userName) {
this
.
userName
= userName;
@Override
public
void
run() {
for
(
int
i=1;i<10;i++){
public
static
void
main(String[] args) {
private
Integer
ticket
=10;
public
void
run() {
public
synchronized
void
fun(){
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
public
static
void
main(String[] args) {
new
Thread(myTread).start();
new
Thread(myTread).start();
new
Thread(myTread).start();
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0)
public
static
void
main(String[] args) {
new
Thread(myTread).start();
new
Thread(myTread).start();
new
Thread(myTread).start();
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0)
public
Thread (Runnable target) {
private
static
synchronized
int
nextThreadNum () {
return
threadInitNumber
++;
public
static
void
main(String[] args) {
new
Thread(myTread).start();
new
Thread(myTread).start();
new
Thread(myTread).start();
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0)
public
static
void
main(String[] args) {
new
Thread(myTread,
"A线程"
).start();
//自己给线程名称
new
Thread(myTread,
"like"
).start();
new
Thread(myTread).start();
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
try
{
public
static
void
main(String[] args) {
new
Thread(myTread,
"A线程"
).start();
//自己给线程名称
new
Thread(myTread,
"like"
).start();
new
Thread(myTread).start();
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
try
{
public
static
void
main(String[] args) {
new
Thread(myTread,
"like"
).start();
new
Thread(myTread).start();
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
try
{
public
static
void
main(String[] args) {
for
(
int
i=0;i<10;i++){
if
(i>2){
try
{
//
TODO
Auto-generated catch block
new
Thread(myTread,
"like"
).start();
new
Thread(myTread).start();
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
try
{
return
;
public
static
void
main(String[] args) {
try
{
//
TODO
Auto-generated catch block
new
Thread(myTread,
"like"
).start();
new
Thread(myTread).start();
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
try
{
public
static
void
main(String[] args) {
public
static
void
main(String[] args) {
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
if
(
ticket
==3){
public
static
void
main(String[] args) {
2.多线程的实现
1.继承Thread类
2.实现runnable接口
3.继承Thread类
public
class
ThreadDemo
extends
Thread{
class
ThreadDemo
extends
Thread{
private
String
userName
;
public
String getUserName() {
return
userName
;
}
public
void
setUserName(String userName) {
this
.
userName
= userName;
}
public
ThreadDemo(String userName) {
this
.
userName
= userName;
}
@Override
public
void
run() {
for
(
int
i=1;i<10;i++){
System.
out
.println(
userName
+i);
}
}
public
static
void
main(String[] args) {
ThreadDemo threadDemo=
new
ThreadDemo (
"线程A"
);
new
ThreadDemo (
"线程A"
);
ThreadDemo threadDemo1=
new
ThreadDemo (
"线程B"
);
new
ThreadDemo (
"线程B"
);
threadDemo.run();
threadDemo1.run();
}
}
结果:
线程A1
线程A2
线程A3
线程A4
线程A5
线程A6
线程A7
线程A8
线程A9
线程B1
线程B2
线程B3
线程B4
线程B5
线程B6
线程B7
线程B8
线程B9
发现并没有实现多线程,如果要正确的启动多线程,则要调用start方法。
代码:
public
class
ThreadDemo
extends
Thread{
class
ThreadDemo
extends
Thread{
private
String
userName
;
public
String getUserName() {
return
userName
;
}
public
void
setUserName(String userName) {
this
.
userName
= userName;
}
public
ThreadDemo(String userName) {
this
.
userName
= userName;
}
@Override
public
void
run() {
for
(
int
i=1;i<10;i++){
System.
out
.println(
userName
+i);
out
.println(
userName
+i);
}
}
public
static
void
main(String[] args) {
ThreadDemo threadDemo=
new
ThreadDemo (
"线程A"
);
new
ThreadDemo (
"线程A"
);
ThreadDemo threadDemo1=
new
ThreadDemo (
"线程B"
);
new
ThreadDemo (
"线程B"
);
threadDemo.start();
threadDemo1.start();
}
}
结果(这只是其中的一种):
线程A1
线程B1
线程A2
线程B2
线程A3
线程B3
线程A4
线程A5
线程A6
线程A7
线程B4
线程A8
线程A9
线程B5
线程B6
线程B7
线程B8
线程B9
为什么要调用start,而不是调用run方法喃?
看源码:
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
;
true
;
}
finally
{
finally
{
try
{
if
(!started) {
group
.threadStartFailed(
this
);
}
}
catch
(Throwable ignore) {
catch
(Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
private
native
void
start0();
返现这里的start0()用了 native ,这个关键字表示调用本机的操作系统函数,因为多线程需要底层操作系统的支持。
如果一个类继承了Thread类,那么一个对象就只能调用一次,如果调用多次,则会抛出异常
public
class
ThreadDemo
extends
Thread{
class
ThreadDemo
extends
Thread{
private
String
userName
;
public
String getUserName() {
return
userName
;
}
public
void
setUserName(String userName) {
this
.
userName
= userName;
}
public
ThreadDemo(String userName) {
this
.
userName
= userName;
}
@Override
public
void
run() {
for
(
int
i=1;i<10;i++){
System.
out
.println(
userName
+i);
out
.println(
userName
+i);
}
}
public
static
void
main(String[] args) {
ThreadDemo threadDemo=
new
ThreadDemo(
"线程A"
);
new
ThreadDemo(
"线程A"
);
ThreadDemo threadDemo1=
new
ThreadDemo(
"线程B"
);
new
ThreadDemo(
"线程B"
);
threadDemo.start();
threadDemo.start();
}
}
结果:
线程A1
线程A2
线程A3
线程A4
线程A5
线程A6
线程A7
Exception in thread "main"
java.lang.IllegalThreadStateException
java.lang.IllegalThreadStateException
at java.lang.Thread.start(
Thread.java:682
)
Thread.java:682
)
at test.ThreadDemo.main(
ThreadDemo.java:34
)
ThreadDemo.java:34
)
线程A8
线程A9
所以如果一个类继承Thread类,想要实现多线程,就有单继承的局限性,所以最好实现runnable接口
4.实现runnable 接口
class
MyTread
implements
Runnable{
MyTread
implements
Runnable{
private
Integer
ticket
=10;
public
void
run() {
fun();
}
public
synchronized
void
fun(){
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
System.
out
.println(
"卖票: ticket="
+
ticket
--);
out
.println(
"卖票: ticket="
+
ticket
--);
}
}
}
};
public
class
ThreadDemo1{
class
ThreadDemo1{
public
static
void
main(String[] args) {
MyTread myTread=
new
MyTread();
new
MyTread();
new
Thread(myTread).start();
new
Thread(myTread).start();
new
Thread(myTread).start();
}
}
这样写:
可以实现多线程的访问(下面的结果是因为锁的原因)
结果:
卖票: ticket=10
卖票: ticket=9
卖票: ticket=8
卖票: ticket=7
卖票: ticket=6
卖票: ticket=5
卖票: ticket=4
卖票: ticket=3
卖票: ticket=2
卖票: ticket=1
如果代码改为这样:
class
MyTread
implements
Runnable{
MyTread
implements
Runnable{
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0)
System.
out
.println(
"票号"
+
ticket
--);
out
.println(
"票号"
+
ticket
--);
}
}
}
public
class
ThreadDemo1{
class
ThreadDemo1{
public
static
void
main(String[] args) {
MyTread myTread=
new
MyTread();
new
MyTread();
new
Thread(myTread).start();
new
Thread(myTread).start();
new
Thread(myTread).start();
}
}
结果:(不唯一)
票号10
票号8
票号9
票号6
票号4
票号3
票号2
票号1
票号7
票号5
5.线程的状态
线程有五种状态
创建状态:一个线程被创建后就处于创建状态,此时它拥有了相应的内存空间和其他资源,但是还处于不可运行状态
就绪状态:当调用线程的时候就进入就绪状态,此时,它将进入线程队列排队,等待CPU服务。
运行状态:CPU调用该资源,自动调用该线程对象的run方法
阻塞状态:CPU暂时中止此线程的进行。
死亡:线程调用stop()或者run()方法运行完成后
6.线程的相关方法
应用方法代码:
取得线程名称:
class
MyTread
implements
Runnable{
MyTread
implements
Runnable{
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0)
System.
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );//取得线程名称,如果自己没有给名称,那么程序就会自动付给一个名称
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );//取得线程名称,如果自己没有给名称,那么程序就会自动付给一个名称
看源码:
public
Thread (Runnable target) {
init(
null
, target,
"Thread-"
+ nextThreadNum(), 0);
null
, target,
"Thread-"
+ nextThreadNum(), 0);
}
private
static
synchronized
int
nextThreadNum () {
return
threadInitNumber
++;
}
}
}
}
public
class
ThreadDemo1 {
class
ThreadDemo1 {
public
static
void
main(String[] args) {
MyTread myTread=
new
MyTread();
new
MyTread();
new
Thread(myTread).start();
new
Thread(myTread).start();
new
Thread(myTread).start();
}
}
结果:
Thread-1票号10
Thread-0票号9
Thread-1票号8
Thread-2票号6
Thread-0票号7
Thread-2票号4
Thread-1票号5
Thread-2票号2
Thread-0票号3
Thread-1票号1
如果给了名称:
class
MyTread
implements
Runnable{
MyTread
implements
Runnable{
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0)
System.
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );
}
}
}
public
class
ThreadDemo1 {
class
ThreadDemo1 {
public
static
void
main(String[] args) {
MyTread myTread=
new
MyTread();
new
MyTread();
new
Thread(myTread,
"A线程"
).start();
//自己给线程名称
new
Thread(myTread,
"like"
).start();
new
Thread(myTread).start();
}
}
结果:
like票号10
like票号9
like票号7
like票号6
A线程票号8
Thread-0票号4
like票号5
Thread-0票号2
A线程票号3
like票号1
补充:
java程序启动的时候至少启动两个程序,一个是:main,一个是垃圾回收机制
线程的休眠:
class
MyTread
implements
Runnable{
MyTread
implements
Runnable{
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
try
{
Thread. sleep(1000);//这里休眠1000ms==1S
}
catch
(InterruptedException e) {
catch
(InterruptedException e) {
e.printStackTrace();
}
System.
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );
}
}
}
}
public
class
ThreadDemo1 {
class
ThreadDemo1 {
public
static
void
main(String[] args) {
MyTread myTread=
new
MyTread();
new
MyTread();
new
Thread(myTread,
"A线程"
).start();
//自己给线程名称
new
Thread(myTread,
"like"
).start();
new
Thread(myTread).start();
}
}
自己打印结果的时候:就会发现有停顿:
like票号10
A线程票号10
Thread-0票号9
like票号8
A线程票号7
Thread-0票号6
like票号5
A线程票号4
Thread-0票号3
like票号2
A线程票号2
Thread-0票号1
like票号0
A线程票号-1
这里出现了-1,是因为在if(ticket>0)判断的时候,上一个线程还没有
ticket
-- ,而另一个线程就已经进入
ticket
-- ,而另一个线程就已经进入
判断线程是否启动:
class
MyTread
implements
Runnable{
MyTread
implements
Runnable{
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
try
{
Thread. sleep(1000);
}
catch
(InterruptedException e) {
catch
(InterruptedException e) {
e.printStackTrace();
}
System.
out
.println(Thread. currentThread().getName()+
"票号"
+
ticket
-- );
out
.println(Thread. currentThread().getName()+
"票号"
+
ticket
-- );
}
}
}
}
public
class
ThreadDemo2 {
class
ThreadDemo2 {
public
static
void
main(String[] args) {
MyTread myTread=
new
MyTread();
new
MyTread();
Thread t=
new
Thread(myTread,
"A线程"
);
//自己给线程名称
new
Thread(myTread,
"A线程"
);
//自己给线程名称
System.
out
.println (
"线程是否启动"
+t.isAlive());
out
.println (
"线程是否启动"
+t.isAlive());
t.start();
//启动线程
//启动线程
System.
out
.println (
"线程是否启动"
+t.isAlive());
out
.println (
"线程是否启动"
+t.isAlive());
new
Thread(myTread,
"like"
).start();
new
Thread(myTread).start();
}
结果:
线程是否启动false
线程是否启动true
like票号10
A线程票号10
Thread-0票号9
A线程票号8
like票号7
Thread-0票号6
A线程票号5
like票号4
Thread-0票号3
A线程票号2
like票号1
Thread-0票号0
A线程票号-1
线程的强制进行:
class
MyTread
implements
Runnable{
MyTread
implements
Runnable{
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
try
{
Thread. sleep(1000);
}
catch
(InterruptedException e) {
catch
(InterruptedException e) {
e.printStackTrace();
}
System.
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );
}
}
}
}
public
class
ThreadDemo2 {
class
ThreadDemo2 {
public
static
void
main(String[] args) {
MyTread myTread=
new
MyTread();
new
MyTread();
Thread t=
new
Thread(myTread,
"A线程"
);
//自己给线程名称
new
Thread(myTread,
"A线程"
);
//自己给线程名称
System.
out
.println(
"线程是否启动"
+t.isAlive());
out
.println(
"线程是否启动"
+t.isAlive());
t.start();
//启动线程
//启动线程
for
(
int
i=0;i<10;i++){
if
(i>2){
try
{
t.join();
//线程的强制惊醒
//线程的强制惊醒
}
catch
(InterruptedException e) {
catch
(InterruptedException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
}
}
System.
out
.println(
"线程是否启动"
+t.isAlive());
out
.println(
"线程是否启动"
+t.isAlive());
new
Thread(myTread,
"like"
).start();
new
Thread(myTread).start();
}
}
结果:
线程是否启动false
A线程票号10
A线程票号9
A线程票号8
A线程票号7
A线程票号6
A线程票号5
A线程票号4
A线程票号3
A线程票号2
A线程票号1
线程是否启动false
为什么第二次判断也是false,那是因为,线程A已经执行完毕,所以已经死亡,自然是false
线程的中止:
class
MyTread1
implements
Runnable{
MyTread1
implements
Runnable{
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
try
{
Thread. sleep(3000);
}
catch
(InterruptedException e) {
catch
(InterruptedException e) {
System.
out
.println(
"A线程被中止"
);
out
.println(
"A线程被中止"
);
return
;
}
System.
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );
}
}
}
}
public
class
ThreadDemo2 {
class
ThreadDemo2 {
public
static
void
main(String[] args) {
MyTread1 myTread=
new
MyTread1();
new
MyTread1();
Thread t=
new
Thread(myTread,
"A线程"
);
//自己给线程名称
new
Thread(myTread,
"A线程"
);
//自己给线程名称
System.
out
.println(
"线程是否启动"
+t.isAlive());
out
.println(
"线程是否启动"
+t.isAlive());
t.start();
//启动线程
//启动线程
try
{
Thread. sleep(2000);
}
catch
(InterruptedException e) {
catch
(InterruptedException e) {
//
TODO
Auto-generated catch block
e.printStackTrace();
}
t.interrupt();
System.
out
.println(
"线程是否启动"
+t.isAlive());
out
.println(
"线程是否启动"
+t.isAlive());
new
Thread(myTread,
"like"
).start();
new
Thread(myTread).start();
}
}
结果:
线程是否启动false
线程是否启动true
A线程被中止
like票号10
Thread-0票号9
like票号8
Thread-0票号7
like票号6
Thread-0票号5
like票号4
Thread-0票号3
like票号2
Thread-0票号1
后台线程:
t.setDaemon(
true
);
true
);
7.线程的优先级
class
MyTread1
implements
Runnable{
MyTread1
implements
Runnable{
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
try
{
Thread. sleep(100);
}
catch
(InterruptedException e) {
catch
(InterruptedException e) {
System.
out
.println(
"A线程被中止"
);
out
.println(
"A线程被中止"
);
}
System.
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );
}
}
}
}
public
class
ThreadDemo2 {
class
ThreadDemo2 {
public
static
void
main(String[] args) {
MyTread1 myTread=
new
MyTread1();
new
MyTread1();
Thread t=
new
Thread(myTread,
"A线程"
);
//自己给线程名称
new
Thread(myTread,
"A线程"
);
//自己给线程名称
Thread t1=
new
Thread(myTread,
"like"
);
new
Thread(myTread,
"like"
);
Thread t2=
new
Thread(myTread);
new
Thread(myTread);
t.setPriority(Thread.
MAX_PRIORITY
);
//设置线程优先级,最大10
MAX_PRIORITY
);
//设置线程优先级,最大10
t1.setPriority(Thread.
MIN_PRIORITY
);最小1
MIN_PRIORITY
);最小1
t2.setPriority(Thread.
NORM_PRIORITY
);5
NORM_PRIORITY
);5
t1.start();
t.start();
//启动线程
//启动线程
t2.start();
}
}
结果:
like票号10
A线程票号8
Thread-0票号9
Thread-0票号7
like票号6
A线程票号5
Thread-0票号4
like票号3
A线程票号2
Thread-0票号1
A线程票号0
like票号-1
这说明不是绝对那个线程的优先级高,就调用那个,而是要看CPU的调度
public
class
ThreadDemo2 {
class
ThreadDemo2 {
public
static
void
main(String[] args) {
// MyTread1 myTread=new MyTread1();
//
// Thread t= new Thread(myTread,"A线程");//自己给线程名称
//
// Thread t1= new Thread(myTread,"like");
// Thread t2= new Thread(myTread);
//
// t.setPriority(Thread.MAX_PRIORITY);//设置线程优先级
// t1.setPriority(Thread.MIN_PRIORITY);
// t2.setPriority(Thread.NORM_PRIORITY);
//
//
// t1.start();
// t.start();//启动线程
// t2.start();
System.
out
.println(Thread.currentThread().getPriority());
//获取主方法的优先级
out
.println(Thread.currentThread().getPriority());
//获取主方法的优先级
}
}
结果:
5
8.线程的礼让:(让当前的线程暂时让个其他线程)
class
MyTread1
implements
Runnable{
MyTread1
implements
Runnable{
private
Integer
ticket
=10;
public
void
run() {
for
(
int
i=0;i<100;i++){
if
(
ticket
>0){
System.
out
.println(Thread.currentThread().getName()+
"----->"
);
//获取线程的名字
out
.println(Thread.currentThread().getName()+
"----->"
);
//获取线程的名字
if
(
ticket
==3){
System.
out
.print(
"线程礼让:"
);
out
.print(
"线程礼让:"
);
Thread.currentThread ().yield();
}
System.
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );
out
.println(Thread.currentThread().getName()+
"票号"
+
ticket
-- );
}
}
}
}
public
class
ThreadDemo2 {
class
ThreadDemo2 {
public
static
void
main(String[] args) {
MyTread1 myTread=
new
MyTread1();
new
MyTread1();
Thread t=
new
Thread(myTread,
"A线程"
);
//自己给线程名称
new
Thread(myTread,
"A线程"
);
//自己给线程名称
Thread t1=
new
Thread(myTread,
"like"
);
new
Thread(myTread,
"like"
);
Thread t2=
new
Thread(myTread);
new
Thread(myTread);
t.setPriority(Thread.
MAX_PRIORITY
);
//设置线程优先级
MAX_PRIORITY
);
//设置线程优先级
t1.setPriority(Thread.
MIN_PRIORITY
);
MIN_PRIORITY
);
t2.setPriority(Thread.
NORM_PRIORITY
);
NORM_PRIORITY
);
t1.start();
t.start();
//启动线程
//启动线程
t2.start();
}
}
结果:
A线程----->
like----->
Thread-0----->
Thread-0票号8
A线程票号10
like票号9
Thread-0----->
like----->
A线程----->
A线程票号5
like票号6
like----->
like票号4
like----->
线程礼让:like票号3
like----->
like票号2
like----->
like票号1
Thread-0票号7
A线程----->
A线程票号0
看看结果:当线程like让出当前线程,但是下一个执行的线程还是like线程,这说明线程的礼让不是绝对的,不是礼让了就一定会让给其他线程