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

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.线程的状态


     线程有五种状态


                         

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


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


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


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


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



6.线程的相关方法





应用方法代码:


          取得线程名称:


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



以上是 java学习之路---线程(重点) 的全部内容, 来源链接: utcz.com/z/393990.html

回到顶部