在说线程原理前,我得先介绍一下到底什么是线程,简单的来说,线程就是不同的两件事,大家都知道现在的操作系统是多任务操作系统,但是它是如何实现多任务的呢,多线程便是它实现多任务的手段之一。那么什么又是进程?这个更容易理解了,每一个应用程序都是一个由一个或多个进程组成的,打开你电脑的任务管理看看就会十分清楚的看到很多个进程在进行着,好了,废话不多说了,进入主题吧。
首先,Java中创建线程的有两种方法,第一种是创建一个类来继承Thread类,那么每个该类的对象都是一个线程了,只要在必要的地方创建对象调用start方法即可启动线程,线程有什么用呢?学过java的人都知道,一个Java应用总是从main()方法开始运行,mian()方法运行在一个线程内,它被称为主线程,同一个线程内程序的运行是从代码的上到下运行的,是一步步执行的。试想一下如果移动公司让你来编写一个查找用户的系统,假如你的程序只有一个主线程,那么得到猴年马月才能查找出一个用户啊(你得知道,移动的用户可是有几个亿那么多啊,大哥)?呵呵,这就得用多线程来解决啦,只要你启动N个线程来分段查找,那么需要的时间必然是大大减少的,仅仅知道了多线程的好处是不行的,还得掌握它才行,
大道理说了这么多,下面看看一个简单的线程例子吧!
//创建一个线程类,让它继承Thread
public class Mythread extends Thread {
private int ID;// 用于线程的标志
public Mythread(int ID) {
this.ID = ID;
}
// 重写Thread中的run方法
public void run() {
int count = 0;
while (true) {
count++;
System.out.println(ID+"线程输出的第" + count + "个数据");
try {
// 让线程休息1秒,否占用CUP过高
Thread.sleep(1000);
} catch (Exception ef) {
ef.printStackTrace();
}
}
}
}
public class StartThread {
public static void main(String[] args) {
// 启动五个线程
for (int i = 0; i < 5; i++) {
Mythread thread = new Mythread(i);
thread.start();
}
// 创建线程对象的另外一种方法,通过匿名内部类实现Runnable接口来创建
java.lang.Runnable run = new java.lang.Runnable() {
public void run() {
int count = 0;
while (true) {
count++;
System.out.println("Runnable线程输出" + count);
try {
Thread.sleep(1000);
} catch (Exception ef) {
ef.printStackTrace();
}
}
}
};
//创建线程
Thread th=new Thread(run);
//启动线程
th.start();
}
}
运行程序,可以看到输出的结果为:
0线程输出的第1个数据
1线程输出的第1个数据
2线程输出的第1个数据
4线程输出的第1个数据
3线程输出的第1个数据
Runnable线程输出1
0线程输出的第2个数据
1线程输出的第2个数据
2线程输出的第2个数据
3线程输出的第2个数据
4线程输出的第2个数据
Runnable线程输出2
1线程输出的第3个数据
2线程输出的第3个数据
0线程输出的第3个数据
3线程输出的第3个数据
4线程输出的第3个数据
细心的你或许会发现,线程前面的编号不每次打印的顺序都一样的,这就涉及到了线程的同步啦,再说这个前,先说一下线程的几种状态,其结构图(此图是COPY过来的,呵呵)如下:
在这里对图解释一下:
1、当我们new了这个对象后,线程就进入了初始状态;
2、当该对象调用了start()方法,就进入可运行状态;
3、进入可运行状态后,当该对象被操作系统选中,获得CPU时间片就会进入运行;
4、进入运行状态后情况就比较复杂了
4.1、run()方法或main()方法结束后,线程就进入终止状态;
4.2、当线程调用了自身的sleep()方法或其他线程的join()方法,就会进入阻塞状态(该状态既停止当前线程,但并不释放所占有的资源)。当sleep()结束或join()结束后,该线程进入可运行状态,继续等待OS分配时间片
4.3、线程调用了yield()方法,意思是放弃当前获得的CPU时间片,回到可运行状态,这时与其他进程处于同等竞争状态,OS有可能会接着又让这个进程进入运行状态;
4.4、当线程刚进入可运行状态(注意,还没运行),发现将要调用的资源被synchroniza(同步),获取不到锁标记,将会立即进入锁池状态,等待获取锁标记(这时的锁池里也许已经有了其他线程在等待获取锁标记,这时它们处于队列状态,既先到先得),一旦线程获得锁标记后,就转入可运行状态,等待OS分配CPU时间片;
4.5、当线程调用wait()方法后会进入等待队列(进入这个状态会释放所占有的所有资源,与阻塞状态不同),进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒(由于notify()只是唤醒一个线程,但我们由不能确定具体唤醒的是哪一个线程,也许我们需要唤醒的线程不能够被唤醒,因此在实际使用时,一般都用notifyAll()方法,唤醒有所线程),线程被唤醒后会进入锁池,等待获取锁标记。
何谓多线程同步?因为多线程给你提了程序的异步执行的功能,所以在必要时必须还提一种同步机制。例如,你想两个线程通讯并共享一个复杂 的数据结构,你需要一种机制让他们相互牵制并正确执行,这就像生产者/消费者机制一样,为这个目的,Java用一种叫监视器(monitor)的机制实现了进程间的异步执行。可以将监视器看作是一个很小的盒子,它只能容纳一个线程。一个线程进入一个监视器,所有其他线程必须等到第一个线程退出监视器后才能进入;监视器可以设计成保护共享的数据不被多个线程同时操 作。大多数多线程系统将监视器设计成对象,Java提了一种更清晰的解决 方案。没有Monitor类;每个对象通过将他们的成员函数定义synchronized来定义自己的显式监视器,一 个线程执行在一个synchronized函数 里, 其他任何线程都不能调用同一个对象的synchronized函 数。
以上有自己的思想,也有从别人那得来的,呵呵···