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学习之路---线程(重点)的更多相关文章

  1. Java学习之路(转)

    Java学习之路(书籍推荐)   一.基础类 1.<Thinking in java>(阅读2遍),入门第一位是建立正确的概念 2.<Core Java>这本书更贴近实践,更多 ...

  2. 新篇章之我的java学习之路下

    昨天写下了人生的第一篇博客,今天接着写我的java学习之路有关开发及框架的学习过程. 想要学好java语言,只学习一些java的基本语法对实际开发中的用处还是不大的,所以我们还要掌握一些有关javaW ...

  3. java学习之路之javaSE基础2

    java学习之路之javaSE基础2 所有的代码都是引用他人写的. 1.逻辑运算符 //&,|,^,! //int x = 10; //5 < x < 15 //x > 5 ...

  4. java学习之路之javaSE基础1

    <h2>java学习之路之javaSE基础1</h2> <div> ###01.01_计算机基础知识(计算机概述)(了解)* A:什么是计算机?计算机在生活中的应用 ...

  5. java学习笔记15--多线程编程基础2

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note15.html,转载请注明源地址. 线程的生命周期 1.线程的生命周期 线程从产生到消亡 ...

  6. JAVA学习之路与大家分享

    这是我四年以前总结的JAVA学习之路,希望对初学者或想从事JAVA开发的人有帮助. 本人是软件工程专业出身,先后学过C.C++.JAVA.VB.delphi等等开发语言以及网络相关管理技术.哎,好久不 ...

  7. Java 学习之路 -- day00

    Java 学习之路 -- day00 Typora 快捷键操作 标题:#+空格 2. *斜体* 3. **加粗** 4. **斜体加粗*** 5. ~~删除线~~ 6. > 引用 7. ···分 ...

  8. (转)如何学习Java技术?谈Java学习之路

    51CTO编者注:这篇文章已经是有数年“网龄”的老文,不过在今天看来仍然经典.如何学习Java?本篇文章可以说也是面对编程初学者的一篇指导文章,其中对于如何学习Java的步骤的介绍,很多也适用于开发领 ...

  9. Java学习之路(书籍推荐)

    一.基础类 1.<Thinking in java>(阅读2遍),入门第一位是建立正确的概念 2.<Core Java>这本书更贴近实践,更多API的介绍,同样,更新也更频繁. ...

随机推荐

  1. WinAPI——钩子函数大全2

    CallNextHookEx 函数功能:该函数发送挂钩信息给当前挂钩链中的下一个挂钩处理过程,一个挂钩处理过程可在对该挂钩信息进行处理之前或之后调用本函数. 函数原形:LRESULT CallNext ...

  2. VS2005下开发PPC2003和WM50编译器一些设置

    1.vs2005开发WM5时,编译器和linker的选项配合问题 链接:http://www.mivi.name/blog/index_en.php?itemid=258 首先说ARM4 ARM4T ...

  3. poj2352Stars

    http://poj.org/problem?id=2352 二维逆序数 按一个数排序 转化为1维的 之前用树状数组写过 这次用线段树敲了下 #include <iostream> #in ...

  4. freemarker跳出循环

    break语句跳出当前循环,如下: <#list table.columns as c>             <#if c.isPK>                 &l ...

  5. poj2478

    比较简单的树形dp; 定义s[i]为节点i的子树节点数和(包括自身):叶子节点s[j]=1; s[i]=signma(s[k])+1 (k是i的孩子) 则i满足的条件是 1.s[k]<=n di ...

  6. ASP.NET 中OAUTH 2.0 及OPENID CONNECT的介绍

        了解以下内容对ASP.NET 5中的验证中间件应用有很大帮助! OAUTH2是目前很多大型网站都使用的对外提供开放资源接口的应用标准,比入taobao\alipay\腾讯\豆瓣等.它和目前的另 ...

  7. UVa 11572 (滑动窗口) Unique Snowflakes

    滑动窗口挺有意思的,如果符合条件右端点一直向前走,不符合的话,左端点向前走. #include <bits/stdc++.h> using namespace std; set<in ...

  8. 百度分享不支持https的解决方案

    站点自从开启 https 之后 ,百度分享就不能用了!但是又寻找不到类似百度分享的替代品.. 怎么办呢?要如何解决 百度分享不支持https的问题呢, 跟着博主动动手,让你百度分享仍然能在https下 ...

  9. GitHub进一步了解

    为什么要引入Git: 1)用简单一点的例子来讲: 一个公司有几个甚至十几个人共同合作开发一款项目的时候,公司对项目代码有明确规范,不可能再像学校做的小项目一样,你觉得哪个同学的代码写的不好,或者和你的 ...

  10. 根据Excel列类型获取列的值

    using System.Data; using System.IO; using System.Text; using System.Web; using NPOI.SS.UserModel; us ...