1.单线程与多线的区别:
单线程的特点:调用的函数一个随另一个函数的结束二开始,如:public void A(){ B(); C();},必须得B函数结束后,C()函数才开始,即函数按顺序调用。
多线程的特点:让多个函数并行执行,故与之单线程比较,多线程的优点:并行执行 节省时间
2.线程、进程、程序的区别:
一个进程包含一个或者多个线程的运行;线程是系统分配CPU运算时间的最小单位,线程之间可以进行数据交换,而进程一般不能;一个程序在处理不同数据集时成为不同的进程,程序是通过进程与数据产生联系的.一个进程肯定有一个与之对应的程序,而且只有一个.而一个程序有可能没有与之对应的进程(没有执行),也有可能有多个进程与之对应(运行在几个不同的数据集上).
(主函数也是一个线程)
3.线程的实现
①继承Thread类实现线程
实现线程,就是用一个类继承Thread,重写Thread类中run()方法,在run()方法中实现实现要执行的方法,而后通过创建该类,调用Thread类的start()方法启动线程,由于run()方法不能传参,故只能在run()方法外面定义变量
/**
* 统计线程,继承Thread
* @author Administrator
*
*/
public class Count extends Thread{
int num;
public Count(int num){
this.num = num;
}
/**
* 重写run()
*/
@Override
public void run(){
countUtil();
}
/**
* 统计方法
*/
public void countUtil(){
……
}
}
public static void main(String args[]){
for(int i=0;i<3;i++){
//创建一个线程对象
Count c1 = new Count(i);
c1.start();
}
}
②实现Runnable接口创建线程
定义一个实现Runnable接口的类,实现它的run()方法,创建该类,将该类包装为Thread类,通过Thread类启动线程。
/**
* 通过集成Runnable实现线程
*
* @author Administrator
*
*/
public class Listener implements Runnable {
private ArrayList<Ball> list;
public Listener(ArrayList<Ball> list) {
this.list = list;
}
public void run() {
while (!Ball.isStop) {
for (int i = 0; i < list.size() - 1; i++) {
Ball b1 = list.get(i);
Ball b2 = list.get(i + 1);
System.out.println(b1.x0 + " " + b1.y0 + "<>" + b2.x0 + " "
+ b2.y0);
}
try {
Thread.sleep(1);
} catch (Exception ef) {
ef.printStackTrace();
}
}
}
}
// 启动监视线程
Listener lis = new Listener(list);
Thread th=new Thread(lis);
th.start();
③以匿名内部类的方式创建线程
匿名内部类中的变量必须定义为final
/**
* 以内部类的形式创建线程
* @author lenovo
*
*/
public class ThreadTest {
public static void main(String args[]){
ThreadTest tt=new ThreadTest();
tt.startTheThread();
}
/**
* 启动线程的方法
*/
public void startTheThread(){
java.lang.Runnable runner=new Runnable(){
public void run(){
……
try{
Thread.sleep(100);
}catch(Exception ef){
ef.printStackTrace();
}
}
};
//创建线程并启动
Thread t=new Thread(runner);
t.start();
}
}
④继承TimerTask类实现线程的定时执行
调度TimerTask对象会定时运行java.util.Timer类。Timer类中有一个常用的方法:
public void schedule(TimerTask task, long delay ,long period)
(调度task对象在程序启动启动delay 毫秒后,每隔period执行一次)
import java.util.Timer;
import java.util.TimerTask;
/**
* 继承TimerTask类实现线程的定时执行
* @author lenovo
*
*/
public class TimerTest extends TimerTask{
public static void main(String args[]){
//创建一个计时器对象
Timer tim=new Timer();
TimerTest tt=new TimerTest();
//程序启动5秒后调度,每隔3秒调度一次
tim.schedule(tt, 5000, 3000);
}
@Override
//重写run()方法,作为线程运行时被调用
public void run() {
}
}
(@Override:强制检测重写父类方法是否正确)
4.线程的监听模式
为了实现对线程的监听,就要在创建一个监听线程,通过队列保存被监听的对象,在监听线程中就能得到被监听对象的属性,进而能对其进行修改。监听线程必须在被监听对象线程启动前启动。
// 通过匿名内部类创建监听器对象
ActionListener alis = new ActionListener() {
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals("开始")) {
Ball.initBall();
// 启动监视线程
Listener lis = new Listener(list);
Thread th=new Thread(lis);
th.start();
Ball b = new Ball(BallUI.this);// 传入窗体
b.start();
list.add(b);
}
}
}
import java.util.ArrayList;
/**
* 监视线程
*
* @author Administrator
*
*/
public class Listener implements Runnable {
private ArrayList<Ball> list;
public Listener(ArrayList<Ball> list) {
this.list = list;
}
public void run() {
while (!Ball.isStop) {
for (int i = 0; i < list.size() - 1; i++) {
Ball b1 = list.get(i);
Ball b2 = list.get(i + 1);
System.out.println(b1.x0 + " " + b1.y0 + "<>" + b2.x0 + " "
+ b2.y0);
}
try {
Thread.sleep(1);
} catch (Exception ef) {
ef.printStackTrace();
}
}
}
}
5.线程的控制
由于jdk中提供的线程的暂停、停止等方法存在安全隐患且已过时,我们必须通过自己编写一个线程控制机制。也就是通过改变循环的条件来实现。
/*
*实现对线程的控制
*/
public class Ball extends Thread {
public static boolean isStop = false;// 是否停止
public static boolean isPause = false;// 是否暂停
public void run() {
move();
}
public void move() {
while (!isStop) {
while (!isPause) {
……
try {
Thread.sleep(1000);// 沉睡时间,球移动位置的时间间隔
} catch (Exception ef) {
ef.printStackTrace();
}
}
try {
Thread.sleep(1);// 沉睡时间,暂停时的休眠
} catch (Exception ef) {
ef.printStackTrace();
}
}
}
/**
* 暂停线程的方法
*/
public static void pauseThread() {
isPause = true;
}
/**
* 继续线程的方法
*/
public static void resumeThread() {
isPause = false;
}
/**
* 停止线程的方法
*/
public static void stopThread() {
isPause = true;
isStop = true;
}
/**
* 停止线程的方法
*/
public static void initBall() {
isPause = false;
isStop = false;
}
}
(有几个循环就要try…catch几次,防止占用cpu过高)
if (command.equals("开始")) {
Baffle.startThread();
Ball.startThread();
// 刷新面板
javax.swing.SwingUtilities.updateComponentTreeUI(panel);
Baffle bf = new Baffle(panel);
panel.addKeyListener(bf);
// 创建线程监听对象
ThreadListener tl = new ThreadListener(panel, start,blist, bf);
tl.start();
bf.start();
Ball b1 = new Ball(panel);
b1.start();
blist.add(b1);
Ball b2 = new Ball(panel);
b2.start();
blist.add(b2);
Ball b3 = new Ball(panel);
b3.start();
blist.add(b3);
Ball b4 = new Ball(panel);
b4.start();
blist.add(b4);
start.setText("暂停");
}
if (command.equals("暂停")) {
Baffle.pauseThread();
Ball.pauseThread();
start.setText("继续");
}
if (command.equals("继续")) {
Baffle.resumeThread();
Ball.resumeThread();
start.setText("暂停");
}
if (command.equals("停止")) {
Baffle.stopThread();
Ball.stopThread();
start.setText("开始");
}