我们现在使用的操作系统几乎都是多任务分时操作系统,多线程的概念也正是应这种操作系统而生的。多任务分时意味着在同一时间可以执行多个程序(比如又在浏览网页,又在听歌,又在聊天).但是实际上是什么情况呢,实际上cpu并没有同时执行这些程序,cpu只是把时间分割成小段小段的时间片,将时间片分配给 正在执行的程序,哪个程序获得时间片哪个程序就开始执行,不等执行完毕,下个程序又获得时间片开始执行,这样多个程序就可以轮流执行一段时间.因为cpu 具有很高的运算能力,所以给人的感觉是这些程序都是同时在执行。
这种正在执行中的程序叫做进程。每一个进程都有自己独立的内存空间和系统资源,每一个进程的内部数据和状态都是完全独立的,所以创建并且执行一个进程的系统开销是比较大的。
于是线程的概念出现了,线程是一段完成某个特定功能的代码.一个系统至少有一个进程,一个进程至少有一个线程,同一个进程的多个线程共享一块内存空间和一组系统资源,所以系统产生一个线程或者在多线程之间切换,负担比进程小得多。多线程意味着一个程序的多行语句可以看上去几乎在同一时间内同时运行,但其实它们之间并不同步。需要注意的是,这使得
线程也有生命周期,线程的状态(state)表明线程处于生命周期的哪个阶段.线程有创建,可运行(runnable),运行中(running),阻塞(blocked),死亡5种状态.通过线程的控制可使线程在这几种状态间转化,每个程序至少拥有一个线程,即所谓的"主线程".当程序加载到内存时,启动主线程.
Java中的多线程就是一个类或者一个程序执行或者管理多个线程执行任务的能力,每个线程可以独立于其他线程而独立运行,也可以和其他线程协同运行,一个类控制着它的所有线程,决定哪个线程得到优先级,哪个线程可以访问其他类的资源,哪个线程开始执行,哪个保持休眠.每一个具有生命的线程总是处于5种状态之一.
用下面一段代码,说明一下线程的用法(下面的方法是实现接口,也可以继承Thread,取决于个人)
{
public void run()
{
System.out.println("My Name is "+Thread.currentThread().getName()); //定义运行的代码
}
public static void main(String[] args)
{
Thread t1=new Thread(new MyThread()); //定义线程实例
Thread t2=new Thread(new MyThread());
Thread t3=new Thread(new MyThread());
t2.setPriority(Thread.MAX_PRIORITY);//赋予最高优先级
t1.start();
t2.start();
t3.start();
}
}
输出结果:
My Name is Thread-1
My Name is Thread-0
My Name is Thread-2
这一节可以记录一些只言片语
1.之所以使用线程,就是想要最大限度地利用cpu资源,不让其空闲。举个例子,比如说,外设的输入输出速度,网络数据的传输速率都远远低于cpu的运算能力,cpu要是一个一个地执行的话,就必须等,这样就造成了资源的浪费。如果在外设输入的时候同时也能进行数据的传输多好,反正外设输入的时候速率很低,也占不了多少资源和时间。
2.一个程序如果要实现多个代码的同时交替进行就需要产生多个线程
3.线程一旦运行起来了就没有办法控制,由cpu随机地分配时间片执行
4.线程是轻量级的,同进程的线程共享该进程的地址空间和资源
5.代码应该写在run方法里面,start是执行线程的唯一方法,每个线程只能start一次。(注意,由于run是public方法,如果直接调用该方法而不用start启动的话,启动的就是方法,而不是线程,程序依然会顺序执行,这样就起不到多线程的作用)。
6.当生成一个线程对象的时候,如果没有为其设定名字,则系统会自动为其生成一个默认格式的名字: Thread-number,比如Thread-1,Thread-2.其中number是自动增加的。
7.如果一个线程类中的变量是成员变量,那么生成多少个对象就有多少份成员变量,比如说只生成了一个对象,那么当多个线程都对这个对象的成员变量进行操作时,只会有一份变量被操作。一个线程对成员变量的改变会影响到另一个线程。
8.如果一个线程类的变量是局部变量,那么无论生成多少个对象,每个线程都会有一份该局部变量的拷贝。因此,一个线程对该局部变量的改变不会影响到其他线程。
9.停止线程的方式:不能使用Thread类自带的stop方法来终止线程的执行。(官方api上说的是该方法已经过时,具有固定的不安全性)。最合适的方法是设定一个变量,在run方法中弄一个循环(设定一个条件,比如boolean
flag=true,用一个while,当被打断的时候,将flag改为false就行),该循环每次都要检测该变量是否满足条件,如果满足就继续执行下去,直到不满足为止,然后跳出循环,线程结束。
10.不能依靠线程的优先级来决定线程的执行顺序,因为优先级是动态的,会根据等待时间等等情况动态的调节,所以不可靠。
12.yield方法
13. 线程优先级
最少是不要调整线程的优先级,这样通常只会把问题转到别的地方。