Java学习——复习 第七天多线程、网络通信、JDBC操作数据库
13 多线程
(1)线程简介—Java语言提供了并发机制,程序员可以在程序中执行多个线程,每一个线程完成一个功能,并与其它线程并发执行,这种机制被称为多线程。一个线程中可以同时包含多个线程,系统会分配给每个进程一点CPU时间片。
(2)实现线程的两种方式
2.1继承Thread类—通过继承Thread类进行创建线程步骤
1)创建一个继承自Thread类的子类
2)覆写Thread类的run方法。
3)创建线程类的一个对象
4)通过线程类的对象调用start方法启动线程(启动后会自动调用覆写的run方法执行线程)
Thread类常用构造方法:
publicThread();创建一个新的线程对象
publicThread(String threadName):创建一个名称为threadName的线程对象。
对线程进行操作使用以下方法
Thread类常用方法 |
|
方法 |
说明 |
interrupt() |
中断线程 |
join() |
等待该线程终止 |
join(long millis) |
等待该线程终止的时间最长为millis毫秒 |
run() |
如果该线程是使用独立的Runnable运行对象构造的,则调用该Runnable对象的run方法;否则,该方法不执行任何操作并返回 |
setPrinrity(int newPriority) |
更改线程的优先级 |
sleep(long millis) |
在制定的毫秒数内让当前正在执行的线程休眠(暂停执行) |
start() |
使该线程开始执行:Java虚拟机调用该线程的run方法 |
yield() |
暂停当前正在执行的线程对象,并执行其他线程 |
代码实现:
public classThreadTest extends Thread { // 指定类继承Thread类
privateint count = 10;
publicvoid run() { // 重写run()方法
while(true) {
System.out.print(count+ " "); // 打印count变量
if(--count == 0) { // 使count变量自减,当自减为0时,退出循环
return;
}
}
}
publicstatic void main(String[] args) {
ThreadTesttest = new ThreadTest();// 创建线程对象
test.start();//启动线程
}
}
运行结果:
10 9 8 7 6 5 43 2 1
2.2实现Runnable接口—如果继承其他类可以通过Runnable接口实现接口
实现Runnable接口需要创建一个Thread对象,并将Runnable对象与Thread对象相关联
1)public Thread(Runnabletarget):分配新的Thread对象,以便将target作为其运行对象
2)publicThrend(Runnable target,String name):分配新的Thread对象,以便将target作为其运行对象,将指定的name作为其名称
使用Runnable接口启动新的线程的步骤
1)建立Runnable对象
2)使用参数为Runnable对象的构造方法创建Thread实例
3)调用start()方法启动线程
代码实现:
public classSwingAndThread extends JFrame {
privateJLabel jl = new JLabel(); // 声明JLabel对象
privatestatic Thread t; // 声明线程对象
privateint count = 0; // 声明计数变量
privateContainer container = getContentPane(); // 声明容器
publicSwingAndThread() {
setBounds(300,200, 250, 100); // 绝对定位窗体大小与位置
container.setLayout(null);// 使窗体不使用任何布局管理器
try{
URLurl = SwingAndThread.class.getResource("1.gif"); // 获取图片的URL
Iconicon = new ImageIcon(url);// 实例化一个Icon
jl.setIcon(icon);// 将图标放置在标签中
}catch (NullPointerException ex) {
System.out.println("图片不存在,请将1.gif拷贝到当前目录下!");
return;
}
//设置图片在标签的最左方
jl.setHorizontalAlignment(SwingConstants.LEFT);
jl.setBounds(10,10, 200, 50); // 设置标签的位置与大小
jl.setOpaque(true);
t= new Thread(new Roll());
t.start();// 启动线程
container.add(jl);// 将标签添加到容器中
setVisible(true);// 使窗体可见
//设置窗体的关闭方式
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
classRoll implements Runnable {// 定义内部类,实现Runnable接口
@Override
publicvoid run() {
while (count <= 200) { // 设置循环条件
//将标签的横坐标用变量表示
jl.setBounds(count,10, 200, 50);
try{
Thread.sleep(1000);// 使线程休眠1000毫秒
}catch (Exception e) {
e.printStackTrace();
}
count+= 4; // 使横坐标每次增加4
if(count == 200) {
// 当图标到达标签的最右边时,使其回到标签最左边
count= 10;
}
}
}
}
publicstatic void main(String[] args) {
newSwingAndThread(); // 实例化一个SwingAndThread对象
}
}
运行结果:这是一个swing窗口,做的图标的循环滚动,注意要把一个图片放在当前目录下
(3)线程的生命周期
线程的整个生命周期,包括五种状态,分别是出生状态、就绪状态、运行状态、暂停状态(包括休眠、等待和阻塞等)和死亡状态
(4)操作线程的方法
4.1线程的休眠—sleep()方法可以使线程进入休眠状态,但需要一个以毫秒为单位的参数,通常在run()方法中循环使用。
代码实现:
public classSleepMethodTest extends JFrame {
/**
*
*/
privatestatic final long serialVersionUID = 1L;
privateThread t;
//定义颜色数组
privatestatic Color[] color = { Color.BLACK, Color.BLUE,Color.CYAN, Color.GREEN, Color.ORANGE,Color.YELLOW,
Color.RED,Color.PINK, Color.LIGHT_GRAY };
privatestatic final Random rand = new Random();// 创建随机对象
privatestatic Color getC() {// 获取随机颜色值的方法
//随机产生一个color数组长度范围内的数字,以此为索引获取颜色
returncolor[rand.nextInt(color.length)];
}
publicSleepMethodTest() {
t= new Thread(new Draw());// 创建匿名线程对象
t.start();//启动线程
}
classDraw implements Runnable {//定义内部类,用来在窗体中绘制线条
intx = 30;// 定义初始坐标
inty = 50;
publicvoid run() {// 覆盖线程接口方法
while(true) {// 无限循环
try{
Thread.sleep(100);//线程休眠0.1秒
}catch (InterruptedException e) {
e.printStackTrace();
}
//获取组件绘图上下文对象
Graphicsgraphics = getGraphics();
graphics.setColor(getC(1));//设置绘图颜色
//绘制直线并递增垂直坐标
graphics.drawLine(x,y, 100, y++);
if(y >= 80) {
y= 50;
}
}
}
privateColor getC(int i) {
//TODO 自动生成的方法存根
returnnull;
}
}
publicstatic void main(String[] args) {
init(newSleepMethodTest(), 100, 100);
}
//初始化程序界面的方法
publicstatic void init(JFrame frame, int width, intheight) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width,height);
frame.setVisible(true);
}
}
4.2线程的加入—当某个线程使用join()方法加入另一个线程时,另一个线程会等该线程执行完毕后再继续执行。
代码实现:
import java.awt.*;
import javax.swing.*;
public class JoinTest extends JFrame {
/**
*
*/
privatestatic final long serialVersionUID = 1L;
privateThread threadA; // 定义两个线程
privateThread threadB;
finalJProgressBar progressBar = new JProgressBar(); // 定义两个进度条组件
finalJProgressBar progressBar2 = new JProgressBar();
intcount = 0;
publicstatic void main(String[] args) {
init(newJoinTest(), 100, 100);
}
publicJoinTest() {
super();
//将进度条设置在窗体最北面
getContentPane().add(progressBar,BorderLayout.NORTH);
//将进度条设置在窗体最南面
getContentPane().add(progressBar2,BorderLayout.SOUTH);
progressBar.setStringPainted(true);// 设置进度条显示数字字符
progressBar2.setStringPainted(true);
//使用匿名内部类形式初始化Thread实例子
threadA= new Thread(new Runnable() {
intcount = 0;
publicvoid run() { // 重写run()方法
while(true) {
progressBar.setValue(++count);// 设置进度条的当前值
try{
Thread.sleep(100);// 使线程A休眠100毫秒
threadB.join();// 使线程B调用join()方法
}catch (Exception e) {
e.printStackTrace();
}
}
}
});
threadA.start();// 启动线程A
threadB= new Thread(new Runnable() {
intcount = 0;
publicvoid run() {
while(true) {
progressBar2.setValue(++count);// 设置进度条的当前值
try{
Thread.sleep(100);// 使线程B休眠100毫秒
}catch (Exception e) {
e.printStackTrace();
}
if(count == 100) // 当count变量增长为100时
break;// 跳出循环
}
}
});
threadB.start();// 启动线程B
}
//设置窗体各种属性方法
publicstatic void init(JFrame frame, int width, int height) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width,height);
frame.setVisible(true);
}
}
运行结果:
4.3线程的中断—在run()方法中使用无限循环形式,然后使用一个布尔型标记控制循环的停止
代码实现:
import java.awt.*;
import javax.swing.*;
public cla