您的位置:首页 > 职场人生

黑马程序员————java基础(多线程)

2014-12-15 21:16 162 查看
进程:

进程是程序在处理机中的一次运行。一个进程既包括其所要执行的指令,也包括了执行指令所需的系统资源,不同进程所占用的系统资源相对独立。所以进程是重量级的任务,它们之间的通信和转换都需要操作系统付出较大的开销。

线程是进程中的一个实体,是被系统独立调度和分派的基本单位。线程自己基本上不拥有系统资源,但它可以与同属一个进程的其他线程共享进程所拥有的全部资源。所以线程是轻量级的任务,它们之间的通信和转换只需要较小的系统开销。

Java支持多线程编程,因此用Java编写的应用程序可以同时执行多个任务。Java的多线程机制使用起来非常方便,用户只需关注程序细节的实现,而不用担心后台的多任务系统。

Java语言里,线程表现为线程类。Thread线程类封装了所有需要的线程操作控制。在设计程序时,必须很清晰地区分开线程对象和运行线程,可以将线程对象看作是运行线程的控制面板。在线程对象里有很多方法来控制一个线程是否运行,睡眠,挂起或停止。线程类是控制线程行为的唯一的手段。一旦一个Java程序启动后,就已经有一个线程在运行。可通过调用Thread.currentThread方法来查看当前运行的是哪一个线程。

进程是程序在处理机中的一次运行。一个进程既包括其所要执行的指令,也包括了执行指令所需的系统资源,不同进程所占用的系统资源相对独立。所以进程是重量级的任务,它们之间的通信和转换都需要操作系统付出较大的开销。

java中通常有两种方式创建线程:

继承Thread类:

可通过继承Thread类并重写其中的run()方法来定义线程体以实现线程的具体行为,然后创建该子类的对象以创建线程。

在继承Thread类的子类ThreadSubclassName中重写run()方法来定义线程体的一般格式为:

<span style="font-family:SimSun;">public class ThreadSubclassName extends Thread{
public ThreadSubclassName(){
..... // 编写子类的构造方法,可缺省
}
public void run(){
..... // 编写自己的线程代码
}
}
//用定义的线程子类ThreadSubclassName创建线程对象的一般格式为:
ThreadSubclassName ThreadObject =
new  ThreadSubclassName();
//然后,就可启动该线程对象表示的线程:
ThreadObject.start();       //启动线程

</span>


实现Runnable接口:

编写多线程程序的另一种的方法是实现Runnable接口。在一个类中实现Runnable接口(以后称实现Runnable接口的类为Runnable类),并在该类中定义run()方法,然后用带有Runnable参数的Thread类构造方法创建线程。

创建线程对象可用下面的两个步骤来完成:

(1)生成Runnable类ClassName的对象

ClassName RunnableObject = new ClassName();

(2)用带有Runnable参数的Thread类构造方法创建线程对象。新创建的线程的指针将指向Runnable类的实例。用该Runnable类的实例为线程提供 run()方法---线程体。

Thread ThreadObject = new Thread(RunnableObject);

然后,就可启动线程对象ThreadObject表示的线程:

ThreadObject.start();

在Thread类中带有Runnable接口的构造方法有:

public Thread(Runnable target);

public Thread(Runnable target, String name);

public Thread(String name);

public Thread(ThreadGroup group,Runnable target);

public Thread(ThreadGroup group,Runnable target,

String name);

其中,参数Runnable target表示该线程执行时运行target的run()方法,String name以指定名字构造线程,ThreadGroup group表示创建线程组。

线程状态的转换:

线程的状态是线程控制的基础。线程状态总的可以分为五大类:生、等待、阻塞、睡眠、死。

生:线程已经被new,且未执行;
start():线程调用start()方法后即进入等待/可运行状态;
yield():此外正在执行的线程也可以通过Thread.yield()方法使当前线程暂停执行,并进入可运行状态,从而让步其他线程,但也可能让步失败,因为该线程可能在进入运行状态后又被再次选中。(注:让步的线程是接着执行线程,还是重新执行,经程序测试是接着执行未执行的代码);
阻塞:线程卡死,或不停执行,跳不出run()方法;
sleep():调用Thread.sleep()方法,使线程暂停执行一段时间,即睡眠,可以用来帮助其他进程获得运行机会;
死:线程执行完毕,执行完run()方法。

线程的同步与锁:

当多个线程同时访问互斥(可交换)数据时,应该同步以保护数据,确保两个线程不会同时更改它。通常用synchronized字段实现,而且只能同步方法或同步代码快。

如果两个线程要执行一个类中的synchronized方法,并且两个线程使用相同的实例来调用方法,那么一次只能有一个线程能够执行方法,另一个需要等待,直到锁被释放

线程的调度:
class TaskR implements Runnable{
public void run() {
System.out.println("正在执行线程B!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("已经执行完线程B!");
}
}
class test {
public static void main(String[] args) throws InterruptedException {
System.out.println("正在执行main函数!");
TaskR b = new TaskR();
Thread threadB = new Thread(b);
System.out.println("准备添加线程B!");
threadB.start();
System.out.println("执行完main");
}
}
class test2 {
public static void main(String[] args) throws InterruptedException {
System.out.println("正在执行main函数!");
TaskR b = new TaskR();
Thread threadB = new Thread(b);
System.out.println("准备添加线程B!");
threadB.start();
System.out.println("threadB.join()");
threadB.join();
System.out.println("执行完main");
}
}


运行test和test2的结果为



在threadB中调用sleep是为了让main函数这条线程获得执行机会。有结果,可知当threadB调用join方法后,即使sleep了main函数都不能跑完,说明join方法的作用,即必须threadB执行完才能继续执行main函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: