java学习之路---线程(重点)
来源:互联网 发布:现货农产品分析软件 编辑:程序博客网 时间:2024/06/05 08:18
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学习之路---线程(重点)
- java基础之线程(重点)
- java学习之路--java对象(1)--重点String类的常用方法
- Practical Java(重点版)之多线程
- Java高级部分之线程重点总结(上)
- Java高级部分之线程重点总结(下)
- (java重点之二)Java并发
- 重点学习线程池ThreadPool
- Java学习提高:反射(*重点*)
- Java学习的重点
- java学习重点
- java学习重点
- Java重点学习笔记
- Java阶段性学习重点
- Practical Java(重点版)之性能
- java基础之集合(重点)
- java基础之IO(重点)
- java学习之线程
- 11月19日
- Linux 安装与多重引导摘要
- CentOS上面对查看svn的帮助信息
- VS调试技巧-汇编,逐语句,逐过程,跳出
- android静默安装apk已经成功实现
- java学习之路---线程(重点)
- 设计模式Strategy
- Java学习笔记-----集合Map
- Redis实战《红丸出品》2.1 Redis数据类型及操作前言
- Qt5—qobject_cast<QAction *>(sender())应用 [2013-11-19整理]
- Android 静默安装/后台安装
- 原型对象与继承
- Glib中Gquark浅析
- 基于Web-Harvest抓取