20.2创建线程
20.2.1继承Thread类
Thread类是Java.lang包中的一个类,从这个类中实例化的对象代表线程,程序员启动一个新线程需要建议Thread实例。
public class ThreadTest extedns Thread{}
run方法格式:
public void run(){}
20.1让线程循环打印1-10
package lx;
public class Demo20_1 extends Thread {
public void run(){
for(int i=0;i<=10;i++) {
System.out.println(i+"");
}
}
public static void main(String[] args) {
Demo20_1 th=new Demo20_1();
th.start();
}
}
20.2.2实现Runnable类
public class Tread extends Object implements Runnable
20.2让窗口的图标移动
package lx;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.*;
public class Demo20_2 extends JFrame {
int c=0;//图标横坐标
public Demo20_2() {
setBounds(300,200,250,100);//绝对定位窗体大小和位置
Container con=getContentPane();//主容器
con.setLayout(null);//使窗体不使用任何布局管理器
Icon img=new ImageIcon("src/1.gif");//图标对象
JLabel jl=new JLabel(img);//显示图标的标签
jl.setBounds(10, 10, 200, 50);//设置标签的位置和大小
Thread t=new Thread() {//定义匿名线程对象
public void run() {
while(true) {
jl.setBounds(c, 10, 200, 50);//将标签的横坐标用线程表示
try {
Thread.sleep(500);//使线程休眠500毫秒
}catch(InterruptedException e) {
e.printStackTrace();
}
c+=4;//使横坐标每次增加4
if(c>=120) {
c=10;//当图标到达标签最右边时,使其回到标签最左边
}
}
}
};
t.start();//启动线程
con.add(jl);//将标签添加到容器中
setVisible(true);//使窗体可见
setDefaultCloseOperation(EXIT_ON_CLOSE);//设置窗体的关闭方式
}
public static void main(String[] args) {
new Demo20_2();
}
}
20.3线程的生命周期
20.4操作线程的方法
20.4.1线程的休眠
sleep方法 该时间以毫秒为单位
-
try{ Thread.sleep(2000); }catch(InterruptedException e){ e.printStackTrace(); }
20.3每0.1秒绘制一条随机颜色的线条
-
package lx; import java.awt.Color; import java.awt.Graphics; import java.util.Random; import javax.swing.JFrame; public class Demo20_3 extends JFrame { private static Color[]color= {//定义颜色数组 Color.BLACK,Color.BLUE,Color.CYAN,Color.GREEN,Color.ORANGE,Color.YELLOW ,Color.RED,Color.PINK,Color.LIGHT_GRAY }; private static final Random rand=new Random(); //创建随机对象 private static Color getC() {//获取随机颜色值的方法 return color[rand.nextInt(color.length)]; } public Demo20_3() { Thread t=new Thread(new Runnable() { //创建匿名线程对象 int x=70; //定义初始坐标 int y=50; public void run() { while(true) {//无限循环 try { Thread.sleep(100);//线程休眠0.1秒 }catch(InterruptedException e){ e.printStackTrace(); } Graphics g= getGraphics();//获取组件绘图上下文对象 g.setColor(getC());//设置绘图颜色 g.drawLine(x, y, 200, y++);//绘制直线并递增垂直坐标 if(y>=100) { y=50; } } } }); t.start();//启动线程 } public static void main(String[] args) { init(new Demo20_3(),300,100); } public static void init(JFrame f,int w,int h) {//初始化程序界面的方法 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setSize(w, h); f.setVisible(true); } }
-
20.4.2线程的加入
当某个线程使用join()方法加入另一个线程时,另一个线程会等待该线程执行完毕后再继续执行。 -
package lx; import java.awt.BorderLayout; import javax.swing.*; public class Demo20_4 extends JFrame{ private Thread A;//定义两个线程 private Thread B; private JProgressBar Bar=new JProgressBar();//定义两个进度条组件 private JProgressBar Bar2=new JProgressBar(); public static void main(String[] args) { Demo20_4 Text=new Demo20_4(); Text.setVisible(true); } public Demo20_4() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(200,200,200,100); getContentPane().add(Bar,BorderLayout.NORTH);//将进度条设置在窗体最北面 getContentPane().add(Bar2,BorderLayout.SOUTH);//将进度条设置在窗体最南面 Bar.setStringPainted(true);//设置进度条显示数字字符 Bar2.setStringPainted(true); A=new Thread(new Runnable() {//使用匿名内部类形式初始化Thread实例 int c=0; public void run() {//重写润()方法 while(true) { Bar.setValue(c++);//设置进度条当前值 try { Thread.sleep(100);//让A线程休眠100毫秒 B.join();//让/B调用join()方法 if(c==30)//设置当A线程走到了30,B线程才启动 B.start();//启动B线程 }catch(InterruptedException e) { e.printStackTrace(); } } } }); A.start();//启动A线程 B=new Thread(new Runnable() { int c=0; public void run() { while(true) { Bar2.setValue(++c);//设置进度条当前值 try { Thread.sleep(100);//让B线程休眠100毫秒 }catch(InterruptedException e) { e.printStackTrace(); } if(c==100)//当c变量增长为100时 break; //跳出循环 } } }); } }
-
20.4让进度条A等待进度条B
20.4.3线程的中断
现在提倡run()方法中使用无限循环的形式,然后使用一个布尔型标记控制循环的停止。 -
package lk; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JProgressBar; public class Demo20_5 extends JFrame{ public Demo20_5(){ JProgressBar Bar=new JProgressBar();//创建进度条 getContentPane().add(Bar,BorderLayout.NORTH);//将进度条设置在窗体最北面 JButton b=new JButton("停止"); getContentPane().add(b,BorderLayout.SOUTH);//将进度条设置在窗体最南面 Bar.setStringPainted(true);//设置进度条显示数字字符 Thread t=new Thread(new Runnable() { int c=0; public void run() { while(true) { Bar.setValue(++c);//设置进度条当前值 try { Thread.sleep(100);//让A线程休眠100毫秒 }catch(InterruptedException e) {//捕捉InterruptedException异常 System.out.println("当前线程程序被中断"); break; } } } }); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { t.interrupt();//中断线程 } }); t.start();//启动线程 } public static void init(JFrame frame,int w,int h) { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(w, h); frame.setVisible(true); } public static void main(String[] args) { init(new Demo20_5(),100,100); } }
-
20.5单机按钮停止进度条滚动
20.4.4线程的礼让
yield()方法使具有同样优先级的线程有进入可执行状态的机会,在当前线程放弃执行权会再回到就绪状态。 -
20.5线程的优先级
每个线程都具有各自的优先级,线程的优先级可以表明在程序中该线程的重要性,如果有会让你多线程处于就绪状态,系统会根据优先级来决定首先使用哪一个线程进入运行状态。 -
package lk; public class Demo20_6 implements Runnable{ String name; public Demo20_6(String name) { this.name=name; } public void run() { String tmp=""; for(int i=0;i<50000;i++) {//完成5万次字符串拼接 tmp+=i; } System.out.println(name+"线程完成任务"); } public static void main(String[] args) { Thread a=new Thread(new Demo20_6("A"));//A线程优先级最小 a.setPriority(1); Thread b=new Thread(new Demo20_6("B")); b.setPriority(3); Thread c=new Thread(new Demo20_6("C")); c.setPriority(7); Thread d=new Thread(new Demo20_6("D"));//D线程优先级最大 d.setPriority(10); a.start(); b.start(); c.start(); d.start(); //线程的执行顺序由CPU决定,所有可能不一定按优先级排序 } }
20.6观察不同优先级的线程执行完毕顺序
20.6线程同步
在单线程程序中,每一次只能做一件事情,后面的事情需要等待前面的事情完成后才可以进行,但是如果使用多线程线程,就会发生两个线程抢占资源问题。20.6.1线程安全
20.6.2线程同步机制
1,同步块
synchronized(Object){
}
2,同步方法
synchronized void f(){}
20.7
package lk;
public class Demo20_6_1 implements Runnable {
int n=10;//设置当前总票数
public synchronized void du() {
if(n>0) {//判断当前票数是否大于 0
try {
Thread.sleep(100); //使当前线程休眠 100毫秒
}
catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"————票数"+n--);//票数减1
}
}
public void run() {
while(true) {//设置无限循环
du();
}
}
public static void main(String[] args) {
Demo20_6_1 t=new Demo20_6_1();//实例化类对象
Thread tA=new Thread(t,"线程一");//以该类对象分别实例化 4 个线程
Thread tB=new Thread(t,"线程二");
Thread tC=new Thread(t,"线程三");
Thread tD=new Thread(t,"线程四");
tA.start();//分别启动线程
tB.start();
tC.start();
tD.start();
}
}