《一》基本概念理解
1.什么是进程?
进程就是在某种程度上相互隔离,独立运行的程序。一般来说,系统都是支持多进程操作的,这所谓的多进程就是让系统好像同时运行多个程序。
2.什么是线程呢?
一个进程可以包含多个线程,在程序中是独立的,并发执行的流,但是与分隔的线程相比,进程中的线程之间的隔离程度要小。他们共享内存,文件句柄和每个线程应有的状态。
3.进程和线程的区别:
(1)一个进程可以包含多个线程,线程比进程具有更高的性能.
这是因为多个线程将共享同一个进程的虚拟空间。线程共享的环境包括:线程代码块,进程的共有数据等。利用这些共享的数据,县城很容易实现相互间的通信。
(2)进程间不能共享内存,线程间共享内存很容易。
(3)系统创建进程需要为该进程分配系统资源,但创建线程则代价小的多,因此使用线程开始先多任务并发比多线程效率高。
《二》线程的应用
1.创建线程的方式一:通过Thread来实现。
Thread()创建一个线程。
Thread(Runnable targer):创建一个线程,并指定一个目标。
Thread(String name ):创建一个名为name 的线程。
Thread(ThreadGroup group ,Runnable targer):创建一个隶属于group线程组的线程。
Thread(ThreadGroup group ,Runnable targer,String name):创建一个隶属于group线程组,目标为target,名字为name的线程。
Thread(ThreadGroup group ,String name):创建一个名字为name,隶属于group的线程组。
用Thread来实现多线程,还包括两种写法。
(1)使用局部内部类的方式实现。如下:红色标记表示不同的地方,请注意看。
public class TestThead {
public static void main(String[] args) {
//调用线程
MyThread myThread = new MyThread();
//启动一个线程
myThread.start();
for (int i = 0; i < 100; i++) {
System.out.println("线程一");
}
}
}
//局部内部类的方式创建。继承Thread类重写run方法。
class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("线程二");
}
}
}
(2)直接继承Thread类。如下:
public class TestThead2 extends Thread { public static void main(String[] args) { //创建本类的对象 TestThead2 testThead2 = new TestThead2(); //创建一个线程 Thread thread = new Thread(testThead2); //启动一个线程 thread.start(); for (int i = 0; i < 100; i++) { System.out.println("线程一"); } } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("线程二"); } } }
2.创建线程的方式二:通过Runnable接口实现多线程的创建。
(1)使用局部内部类的方法
public class TestThead3 { public static void main(String[] args) { // 启动线程 ThreeThread target = new ThreeThread(); Thread thread = new Thread(target); thread.start(); for (int i = 0; i < 100; i++) { System.out.println("线程一"); } } } class ThreeThread implements Runnable { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("线程二"); } }
(2)直接继承接口
public class TestThead5 implements Runnable { public static void main(String[] args) { // 启动线程 ThreeThread5 target = new ThreeThread5(); Thread thread = new Thread(target); thread.start(); for (int i = 0; i < 100; i++) { System.out.println("线程一"); } } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("线程二"); } } }
3.两种创建线程的方法比较
(1)使用Runnable接口
可以将CPU,代码和数据分开,形成清晰的模型。
使用接口后,该类还可以继承别的类。
保持程序风格一致。
(2) 使用Thread类
不能再从其他类继承。
编写简单,可以直接操作线程,无需使用Thread.currentThread().
4.守护线程。
有一种线程,他是从后台运行的,他的任务是为其他线程提供服务,这种线程被称为守护线程。 典型的案例:定时器(Timer)
(1)setDaemon(boolean d):把普通线程设置为守护线程(又叫:后台线程)
(2)isDaemon():测试特定线程是否是后台线程。
例子如下:
package com.zyy; // 线程的优先级 public class MyDaemon { public static void main(String[] args) { Run run = new Run(); Thread th1 = new Thread(run); th1.setDaemon(true); System.out.println(th1.isDaemon());// 判断某个线程是不是守护线程。 th1.start(); for(int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()+"--"+i); } } } class Run implements Runnable{ @Override public void run() { while(true){ System.out.println("我是守护线程"); } } }
5.线程的状态
进程可以分为五中状态:新建,就绪,运行,阻塞,死亡
(1)当使用new来创建一个线程的时候,他处于new状态,这时候,线程并没有进行任何的操作。
(2)当使用线程的start()方法时候,想线程调度程序注册一个线程,这个时候这个线程就就绪了,就等待CPU给他分配时间了。
(3)调用线程的Run方法给已经注册的线程,执行的机会。进入运行状态。
(4)当run方法执行完毕后,线程将被抛弃。进入死亡状态。
(5)如果线程在运行状态中因为IO阻塞,等待键盘输入,调用线程的sleep(),wait()方法,线程就会进入阻塞状态,以上导致阻塞的因素消失了,如“输入结束”,则进入就绪状态,继续等待CPU分配的时间。
6.线程的结束方式
线程有三种结束方式:
(1)运行到run方法的结尾,自动结束
(2)线程抛出一个未捕获的异常
(3)另一个线程调用Deprecate的stop()方法,由于这个方法会引起线程的不安全问题,所以已经不推荐使用了。
7.线程的优先级
getPriority()、setPriority得到和设置当前线程的优先级。优先级1-10,如果不指定默认是5.理论上,谁优先级高,谁被cpu调度的可能性就大。但是优先级低的并不是不执行。资源不足的时候才有效果。这个只是程序员实行的建议权。
举个例子:
public class TestProprity { public static void main(String[] args) { myRun myRun = new myRun(); Thread thread1 = new Thread(myRun,"乌龟4"); thread1.start(); thread1.setPriority(4); Thread thread2 = new Thread(myRun,"乌龟10"); thread2.start(); thread2.setPriority(10); Thread.currentThread().setName("兔子"); for (int i = 0; i < 100; i++) { System.out.println("线程一"+Thread.currentThread().getName()+Thread.currentThread().getPriority()); } } } class myRun implements Runnable { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("线程二"+Thread.currentThread().getName()); } } }
8.线程的其他常用方法。
1. sleep:让当前线程停止执行(休眠)一段时间。
2. join:如果在A线程中B线程join进来,则现在执行B的内容,直到B执行完毕才继续执行A。比如A是显示数据 B是收集收据。
3. yield:让位:让出执行权,和其他线程争夺资源,谁拿到cpu时间片谁执行。
4. wait:线程进入等待状态,等待notify()的唤醒。
《三》定时器的应用
public class TestTimer extends JFrame { private static final long serialVersionUID = 1L; private JLabel lbshow; private int niIndex=2; public TestTimer() { JPanel basicJPanel = new JPanel(); basicJPanel.setLayout(new BorderLayout()); lbshow = new JLabel(); lbshow.setIcon(new ImageIcon("logo/1.png")); basicJPanel.add(lbshow, BorderLayout.CENTER); setContentPane(basicJPanel); setBounds(200, 200, 410, 320); setVisible(true); Timer timer = new Timer(); myTimerTask task = new myTimerTask(); //第一参数:到了时间要执行的目标,二:多长时间之后开始进行计时。三:每隔1S执行一次。 timer.schedule(task,1000, 1000); } public class myTimerTask extends TimerTask { @Override public void run() { // TODO Auto-generated method stub if(niIndex<7) { niIndex++; lbshow.setIcon(new ImageIcon("logo/"+niIndex+".png")); } } } public static void main(String[] args) { new TestTimer(); } }