java学习之路---线程(重点)

 1.多线程是一种并发机制的有效手段。进程和线程一样,都是实现并发的一个基本单位。线程是比进程更小的一种实现单位,线程是在进程的基础上的进一步划分。所谓的多线就是在一个进程中产生了多个线程,这些线程可以同时存在,同时运行。
2.多线程的实现
          1.继承Thread类
          2.实现runnable接口


3.继承Thread类
public 
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" 
);
           ThreadDemo threadDemo1=
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{
     
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" 
);
           ThreadDemo threadDemo1=
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
;
        } 
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 */
            }
        }
    }

    
private 
native 
void 
start0();

返现这里的start0()用了 native ,这个关键字表示调用本机的操作系统函数,因为多线程需要底层操作系统的支持。



如果一个类继承了Thread类,那么一个对象就只能调用一次,如果调用多次,则会抛出异常

public 
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" 
);
          ThreadDemo threadDemo1=
new 
ThreadDemo( 
"线程B"
);
          threadDemo.start();
          threadDemo.start();
     }

}
结果:
线程A1
线程A2
线程A3
线程A4
线程A5
线程A6
线程A7
Exception in thread "main" 
java.lang.IllegalThreadStateException
     at java.lang.Thread.start( 
Thread.java:682
)
     at test.ThreadDemo.main( 
ThreadDemo.java:34
)
线程A8
线程A9

所以如果一个类继承Thread类,想要实现多线程,就有单继承的局限性,所以最好实现runnable接口

4.实现runnable 接口

class 
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
--);
                   
              }
     
          
     }
     }
};

public 
class 
ThreadDemo1{
           
public 
static 
void 
main(String[] args) {
              MyTread 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{
     
private
  Integer  
ticket
=10;
     
public 
void 
run() {
           
for
(
int 
i=0;i<100;i++){
               
if
(
ticket 
>0)
              System. 
out
.println(
"票号" 
+
ticket 
--);
              
          }
          
          
     }
     
}
public 
class 
ThreadDemo1{
           
public 
static 
void 
main(String[] args) {
              MyTread 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.线程的状态

     线程有五种状态
java学习之路---线程(重点)

                         
java学习之路---线程(重点)
创建状态:一个线程被创建后就处于创建状态,此时它拥有了相应的内存空间和其他资源,但是还处于不可运行状态

就绪状态:当调用线程的时候就进入就绪状态,此时,它将进入线程队列排队,等待CPU服务。

运行状态:CPU调用该资源,自动调用该线程对象的run方法

阻塞状态:CPU暂时中止此线程的进行。

死亡:线程调用stop()或者run()方法运行完成后


6.线程的相关方法
java学习之路---线程(重点)
java学习之路---线程(重点)



应用方法代码:

          取得线程名称:

class
 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 
-- );//取得线程名称,如果自己没有给名称,那么程序就会自动付给一个名称

看源码:


   
 public
 Thread (Runnable target) {
        init( 
null
 , target, 
"Thread-" 
nextThreadNum(), 0);
    }

 
 private
 
static
 
synchronized 
int
 nextThreadNum () {
        
return
 
threadInitNumber 
++;
    }


              
          }
          
          
     }
     
}
public
 
class 
ThreadDemo1 {
           
public
 
static 
void
 main(String[] args) {
              MyTread 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{
     
 private
  Integer  
ticket
=10;
     
 public
 
void
 run() {
           
for
 (
int 
i=0;i<100;i++){
               
if
 (
ticket 
>0)
               System. 
out
 .println(Thread.currentThread().getName()+ 
"票号"
 +
ticket 
-- );
              
          }
          
          
     }
     
}
public
 
class 
ThreadDemo1 {
           
public
 
static 
void
 main(String[] args) {
              MyTread 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{
     
 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) {
                        
                        e.printStackTrace();
                   }
               System. 
out
 .println(Thread.currentThread().getName()+ 
"票号"
 +
ticket 
-- );
              }
              
          }
          
          
     }
     
}
public
 
class 
ThreadDemo1 {
           
public
 
static 
void
 main(String[] args) {
              MyTread 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 
-- ,而另一个线程就已经进入





判断线程是否启动:

class
 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) {
                        
                        e.printStackTrace();
                   }
               System. 
out
 .println(Thread. currentThread().getName()+
 "票号"

ticket
-- );
              }
              
          }
          
          
     }
     
}
public
 
class 
ThreadDemo2 {
     
     
 public
 
static
 
void 
main(String[] args) {
          MyTread myTread= 
new
 MyTread();
          
     Thread t=  
new
 Thread(myTread,
"A线程" 
);
//自己给线程名称
     System.
 out
.println (
"线程是否启动" 
+t.isAlive());
     
     t.start(); 
//启动线程
     
     System.
 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{
     
 private
  Integer  
ticket
=10;
     
 public
 
void
 run() {
           
for
 (
int 
i=0;i<100;i++){
               
if
 (
ticket 
>0){
                    
try
 {
                        Thread. sleep(1000);
                   } 
catch
 (InterruptedException e) {
                        
                        e.printStackTrace();
                   }
               System. 
out
 .println(Thread.currentThread().getName()+ 
"票号"
 +
ticket 
-- );
              }
              
          }
          
          
     }
     
}
public
 
class 
ThreadDemo2 {
     
     
 public
 
static
 
void 
main(String[] args) {
          MyTread myTread= 
new
 MyTread();
          
     Thread t=  
new
 Thread(myTread,
"A线程" 
);
//自己给线程名称
     System.
 out
.println( 
"线程是否启动" 
+t.isAlive());
     
     t.start(); 
//启动线程
     
     
 for
(
 int
 i=0;i<10;i++){
           
if
 (i>2){
               
try
 {
                   t.join(); 
//线程的强制惊醒
              } 
catch
 (InterruptedException e) {
                    
// 
TODO
 Auto-generated catch block
                   e.printStackTrace();
              }
          }
     }
     System.
 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{
     
 private
  Integer  
ticket
=10;
     
 public
 
void
 run() {
           
for
 (
int 
i=0;i<100;i++){
               
if
 (
ticket 
>0){
                    
try
 {
                        Thread. sleep(3000);
                   } 
catch
 (InterruptedException e) {
                        System. 
out
 .println(
"A线程被中止" 
);
                         
return
 ;
                   }
               System. 
out
 .println(Thread.currentThread().getName()+ 
"票号"
 +
ticket 
-- );
              }
              
          }
          
          
     }
     
}
public
 
class 
ThreadDemo2 {
     
     
 public
 
static
 
void 
main(String[] args) {
          MyTread1 myTread= 
new
 MyTread1();
          
     Thread t=  
new
 Thread(myTread,
"A线程" 
);
//自己给线程名称
     System.
 out
.println( 
"线程是否启动" 
+t.isAlive());
     
     t.start(); 
//启动线程
     
 try
 {
          Thread. sleep(2000);
     } 
catch
 (InterruptedException e) {
           
// 
TODO
 Auto-generated catch block
          e.printStackTrace();
     }
     
     t.interrupt();
     
     System.
 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
);



7.线程的优先级

class
 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) {
                        System. 
out
 .println(
"A线程被中止" 
);
                   }
               System. 
out
 .println(Thread.currentThread().getName()+ 
"票号"
 +
ticket 
-- );
              }
              
          }
          
          
     }
     
}
public
 
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
 );
//设置线程优先级,最大10
          t1.setPriority(Thread. 
MIN_PRIORITY
 );最小1
          t2.setPriority(Thread. 
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 {
     
     
 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()); 
//获取主方法的优先级
          
     }

}

结果:
5


8.线程的礼让:(让当前的线程暂时让个其他线程)

class
 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()+ 
"----->"
 );
//获取线程的名字
                    
if
 (
ticket 
==3){
                        System. 
out
 .print(
"线程礼让:" 
);
                         Thread.currentThread ().yield();
                   }
               System. 
out
 .println(Thread.currentThread().getName()+ 
"票号"
 +
ticket 
-- );
              }
              
          }
          
          
     }
     
}
public
 
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();
          
     }

}

结果:
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线程,这说明线程的礼让不是绝对的,不是礼让了就一定会让给其他线程

上一篇:Flume启动报错[ERROR - org.apache.flume.sink.hdfs. Hit max consecutive under-replication rotations (30); will not continue rolling files under this path due to under-replication解决办法(图文详解)


下一篇:连接redis错误:ERR Client sent AUTH, but no password is set