线程是指进程内的一个执行单元,也是进程内的可调度实体.
与进程的区别:
(1)地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间;
(2)资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
(3)线程是处理器调度的基本单位,但进程不是.
4)二者均可并发执行.
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于:
简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
在开发过程中我们往往会遇到一些要用到多线程操作的变成问题,现在我就讲解一下线程的创建:
第一中方式继承Thread类
在java API中找到Thread类具体介绍这个类的作用如下:
线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。
每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread
对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护程序。
当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的 main
方法)。Java 虚拟机会继续执行线程,直到下列任一情况出现时为止:
- 调用了
Runtime
类的exit
方法,并且安全管理器允许退出操作发生。 - 非守护线程的所有线程都已停止运行,无论是通过从对 run 方法的调用中返回,还是通过抛出一个传播到
run
方法之外的异常。
创建新执行线程有两种方法。一种方法是将类声明为 Thread
的子类。该子类应重写 Thread
类的 run
方法。接下来可以分配并启动该子类的实例。
通过看这个Thread线程的API我们可以看出这个线程是继承根类(Object)实现了Runable接口,Runable接口在另一种方式中会介绍到。
现在我们看看这个Thread类中有的一些方法:
主要讲 run()
、start()
、sleep(long millis)
还有一些其他的方法如果有人喜欢研究一下的话可以连接
http://tool.oschina.net/uploads/apidocs/jdk-zh/index.html?overview-summary.html
这个地址来看一下其他方法的作用
run()方法:
public void run()如果该线程是使用独立的
Runnable
运行对象构造的,则调用该
Runnable
对象的
run
方法;否则,该方法不执行任何操作并返回。
Thread
的子类应该重写该方法。
我们要写的一些要运行的代码块(要实现的一些功能)都是在这个方法中编写。
start()方法:
public void start()使该线程开始执行;Java 虚拟机调用该线程的
run
方法。
结果是两个线程并发地运行;当前线程(从调用返回给 start
方法)和另一个线程(执行其 run
方法)。
多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
我们每次执行时都是调用的start方法来执行run方法中的内容,具体是怎么调用run方法的请看java源码。
sleep()方法:
public static void sleep(long millis) throws InterruptedException在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。
是指让当前正在执行的线程进入睡眠状态(这个时间是按照毫秒计算的)
现在我们来编写一个线程:
public class bookThread extends Thread {
public String name;
public void run(){
for(int i=0;i<1000;i++) {
System.out.println(this.name+"要吃了"+i+"个糖");
}
}
}
现在我们来看一下第二中创建线程的方式:
第二种方式就是实现runnable接口;
public interface Runnable
Runnable
接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run
的无参数方法。
设计该接口的目的是为希望在活动时执行代码的对象提供一个公共协议。例如,Thread
类实现了 Runnable
。激活的意思是说某个线程已启动并且尚未停止。
此外,Runnable
为非 Thread
子类的类提供了一种激活方式。通过实例化某个 Thread
实例并将自身作为运行目标,就可以运行实现 Runnable
的类而无需创建 Thread
的子类。大多数情况下,如果只想重写 run()
方法,而不重写其他 Thread
方法,那么应使用 Runnable
接口。这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应为该类创建子类。
这个接口只有一个run()方法:
void run()
使用实现接口 Runnable
的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run
方法。
这个run方法就是我们上边被覆盖的那个run方法。可以看到这是一个无参的、返回类型为空
现在我们通过实现Runnable接口来创建一个线程;
public class bookThread2 implements Runnable{
public String name;
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<1000;i++) {
System.out.println(this.name+"要吃了"+i+"个糖");
}
}
}
现在我们来创建一个主线程来测试一下;
public class ThreadTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
bookThread thread1=new bookThread();
bookThread thread2=new bookThread();
thread1.name="张三";
thread2.name="李四";
thread1.start();
thread2.start();
}
}
通过运行我们可以看到这两个线程是交替执行的。这个在以后再说。