JAVA多线程

来源:互联网 发布:手机广播软件 编辑:程序博客网 时间:2024/06/14 08:58

1、程序、进程与线程
程序是计算机指令的集合,它以文件的形式存储在磁盘上。
进程:是一个程序在其自身的地址空间中的一次执行活动
进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;而程序不能申请系统资源,不能被系统调度,也不能作为独立运行的单位,因此,它不占用系统的运行资源
线程:是进程中的一个单一的连续控制流程。一个进程可以拥有多个线程。
线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单。

 

Java运行环境——单进程多线程
多线程的目的是为了最大限度的利用CPU资源。
Java编写程序都运行在在JVM中,在JVM的内部,程序的多任务是通过线程来实现的。启动一个java应用程序,就会启动一个JVM进程。在同一个JVM进程中,有且只有一个进程,就是它自己。在这个JVM环境中,所有程序代码的运行都是以线程来运行。

 

Java线程实现的两种方式
Java在语言级提供了对多线程程序设计的支持。
实现多线程程序的两种方式:
    (1)从Thread类继承;
    (2)实现Runnable接口。

 

继承Thread类
Thread类定义在java.lang包中,一个类只要继承了Thread类,此类就称为多线程操作类。在Thread子类中,必须明确的覆写Thread类中的run()方法,此方法为线程的主体
class 类名 extends Thread{
    //属性;
    //方法;
    //覆写Thread类中的run()方法,此方法是线程的文体
 Public void run(){
 //线程文体。
 }
}

class MyThread extends Thread{
    private String name;
    public MyThread(String name){
        this.name = name;
    }
    public void run(){
        for(int i=0; i<10; i++){
            System.out.println(name +”运行:”+i);
        }
    }
}

public class ThreadDemo1{
    public static void main(String args[]){
        MyThread mt1=new MyThread(“线程A”);
        MyTHread mt2=new Mythread(“线程B”);

        mt1.start();  
        mt2.start();
    }
}

线程类的使用误区:
直接调用线程run方法,并不会让一个线程启动,其效果实际上与一般的方法调用一样,只是在主线程中执行。
让一个线程启动的正确方法是使用Thread类定义中的start()方法。

public class ThreadDemo1{
    public static void main(String args[]){
        MyThread mt1=new MyThread(“线程A”);
        MyTHread mt2=new Mythread(“线程B”);

        mt1.start();  
        mt2.start();
    }
}

线程调度
调度的方式分为:分时调度,抢占式调度
java虚拟机是抢占式调度,在java编程中,抢占式调度是指根据优先级来获得CPU的分配使用,如果同级则是根据随机选择。

 

Runnable
通过实现Runnable接口的方式来实现多线程,Runnable接口中只定义了一个抽象方法:
public void run();
通过Runnable接口实现多线程:
class 类名 implements Runnable{
    //属性;
    //方法;  
    //覆写Runnable接口的run()方法
    public void run(){ ……} //线程主体
}
Class MyThread implements Runnable{
    private String name;
    public MyThread(String name){
        this.name = name;
    }
    public void run(){
        for(int i=0;i<10;i++){
            System.out.println(name+”运行:”+i);
        }
    }
}

public class RunnableDemo{
    MyThread mt1= new MyThread(“线程A”);
    MyThread mt2 = new MyThread(“线程B”);
       
    Thread t1 = new Thread(mt1);
    Thread t2 = new Thread(mt2);
    t1.start();
    t2.start();
}

 

Thread类与Runnable接口的联系
Thread类的定义
public class Thread extends Object implements Runnable{
    public Thread(Runnable){
        init(null, target, name, 0);
    }

    private void init(…, Runnable target,…){
        ……
        this.target = target;
    }

    public void run(){
        target.run();
    }

}

使用Thread类在操作多线程的时时候无法达到资源共享的目的,而使用Runnable接口实现的多线程操作可以实现资源共享。

 

Thread类与Runnable接口的区别
Runnable较Thread类的优点:
适合多个相同程序代码的线程去处理同一个资源;
可以避免由于单继承局限所带来的影响
增强了程序的健壮性,代码能够被多个线程共享

线程的状态
多线程在操作中也是有一个固定的操作状态:
创建状态:准备好了一个多线程对象:Thread = new Thread();
就绪状态:调用了start()方法,等待CPU进行调度
运行状态:执行run()方法
阻塞状态:暂时停止执行,可能将资源交给其他线程使用
终止状态(死亡状态):线程执行完毕,不再使用

 

线程的同步与死锁
什么时候需要线程同步?
火车票出售,将不同的售票点当成不同的线程,那这些线程都共享同一份数据——火车票。A售票点工作人员查询系统,目前还有1张票,准备出售时,有急事离开一会,此时,B售票点工作人员查询系统,还有1张票,出票,A工作人员回来后,再出售车票,此时票数不对了。

资源共享的问题
Class MyThread implements Runnable{
    private int ticket = 5;
    public void run(){
        for(int i=0; i<100; i++){
            if(ticket>0){
                try{
                    Thread.sleep(300);
                }catch(InterruptedException  e){
                    e.printStackTrace();
                }
                System.out.println(“票数:”+ticket--);
            }
        }
    }
}

Public class TestDemo{
     MyThread mt = new MyThread();
     Thread t1 = new Thread(mt);
     Thread t2 = new Thread(mt);
     Thread t3 = new Thread(mt);
     t1.start();
     t2.start();
     t3.start();
}

 

如何进行线程同步
解决资源共享的同步操作问题,有两种方式:

1,同步代码块:
synchronized(同步对象){
    // 需要同步的代码;
}
同步的时候必须指明同步的对象,一般情况下会将当前对象作为同步对象,用this变量引用。

2,同步方法:
除了可以将需要的代码进行同步之外,也可以将一个方法声明为同步方法。
同步方法定义格式:
syschronized 方法返回类型  方法名(参数列表){
    //方法体
}

 

线程死锁
资源共享时需要进行同步操作。
程序中过多的同步可能产生死锁

原创粉丝点击