提交 5a01809c 编写于 作者: 御承扬

Update

上级 7b42fd47
public class Hello {
public static void main(String[] args){
System.out.println("Hello World");
}
}
\ No newline at end of file
package 测试代码专用;
// !/usr/bin/env jdk1.8
// encoding:utf-8
//@software:IntelliJ IDEA
//@pack:测试代码专用
//@user:彭友聪
//@date:2019/6/24
//@time:21:19
//@project:IDEA_JAVA
//@file:KeyBoardTest.java
//Author:御承扬
//email:2923616405@qq.com
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.Color;
import java.awt.Component;
import javax.swing.JButton;
import java.awt.Font;
import javax.swing.SwingConstants;
import javax.swing.border.TitledBorder;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.JTextField;
/**
* 虚拟键盘(键盘的按下与释放)
*/
public class KeyBoardTest extends JFrame { //创建“键盘”类继承JFrame
//声明窗体中的成员组件
private JPanel contentPane;
private JTextField textField;
private JButton btnQ;
private JButton btnW;
private JButton btnE;
private JButton btnR;
private JButton btnT;
private JButton btnY;
private JButton btnU;
private JButton btnI;
private JButton btnO;
private JButton btnP;
private JButton btnA;
private JButton btnS;
private JButton btnD;
private JButton btnF;
private JButton btnG;
private JButton btnH;
private JButton btnJ;
private JButton btnK;
private JButton btnL;
private JButton btnZ;
private JButton btnX;
private JButton btnC;
private JButton btnV;
private JButton btnB;
private JButton btnN;
private JButton btnM;
Color green=Color.GREEN;//定义Color对象,用来表示按下键的颜色
Color white=Color.WHITE;//定义Color对象,用来表示释放键的颜色
ArrayList<JButton> btns=new ArrayList<JButton>();//定义一个集合,用来存储所有的按键ID
//自定义一个方法,用来将容器中的所有JButton组件添加到集合中
private void addButtons(){
for(Component cmp :contentPane.getComponents()){//遍历面板中的所有组件
if(cmp instanceof JButton){//判断组件的类型是否为JButton类型
btns.add((JButton)cmp);//将JButton组件添加到集合中
}
}
}
/**
* 主方法
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() { //使得Runnable中的的run()方法在the system EventQueue的指派线程中被调用
public void run() {
try {
KeyBoardTest frame = new KeyBoardTest(); //创建KeyBoard对象
frame.setVisible(true); //使frame可视
frame.addButtons();//初始化存储所有按键的集合
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* 创建JFrame窗体
*/
public KeyBoardTest() { //KeyBoard的构造方法
setTitle("\u865A\u62DF\u952E\u76D8\uFF08\u6A21\u62DF\u952E\u76D8\u7684\u6309\u4E0B\u4E0E\u91CA\u653E\uFF09"); //设置窗体题目
setResizable(false); //不可改变窗体宽高
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置窗体关闭的方式
setBounds(100, 100, 548, 280); //设置窗体的位置和宽高
/**
* 创建JPanel面板contentPane置于JFrame窗体中,并设置面板的背景色、边距和布局
*/
contentPane = new JPanel();
contentPane.setBackground(Color.WHITE);
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
/**
* 创建按钮button置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnQ = new JButton("Q");
btnQ.setBackground(white);
btnQ.setVerticalAlignment(SwingConstants.TOP);
btnQ.setHorizontalAlignment(SwingConstants.LEADING);
btnQ.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnQ.setBounds(0, 60, 47, 45);
contentPane.add(btnQ);
/**
* 创建按钮button_2置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnW = new JButton("W");
btnW.setBackground(white);
btnW.setVerticalAlignment(SwingConstants.TOP);
btnW.setHorizontalAlignment(SwingConstants.LEADING);
btnW.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnW.setBounds(55, 60, 49, 45);
contentPane.add(btnW);
/**
* 创建按钮button_3置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnE = new JButton("E");
btnE.setBackground(white);
btnE.setVerticalAlignment(SwingConstants.TOP);
btnE.setHorizontalAlignment(SwingConstants.LEADING);
btnE.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnE.setBounds(110, 60, 45, 45);
contentPane.add(btnE);
/**
* 创建按钮button_4置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnR = new JButton("R");
btnR.setBackground(white);
btnR.setVerticalAlignment(SwingConstants.TOP);
btnR.setHorizontalAlignment(SwingConstants.LEADING);
btnR.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnR.setBounds(165, 60, 45, 45);
contentPane.add(btnR);
/**
* 创建按钮button_5置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnF = new JButton("F");
btnF.setBackground(white);
btnF.setVerticalAlignment(SwingConstants.TOP);
btnF.setHorizontalAlignment(SwingConstants.LEADING);
btnF.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnF.setBounds(195, 125, 45, 45);
contentPane.add(btnF);
/**
* 创建按钮button_6置于面板contentPane中,设置按钮的背景色、位置、宽高以及按钮中的字体位置、内容、样式
*/
btnD = new JButton("D");
btnD.setBackground(white);
btnD.setVerticalAlignment(SwingConstants.TOP);
btnD.setHorizontalAlignment(SwingConstants.LEADING);
btnD.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnD.setBounds(137, 125, 45, 45);
contentPane.add(btnD);
btnT = new JButton("T");
btnT.setVerticalAlignment(SwingConstants.TOP);
btnT.setHorizontalAlignment(SwingConstants.LEADING);
btnT.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnT.setBackground(white);
btnT.setBounds(220, 60, 45, 45);
contentPane.add(btnT);
btnY = new JButton("Y");
btnY.setVerticalAlignment(SwingConstants.TOP);
btnY.setHorizontalAlignment(SwingConstants.LEADING);
btnY.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnY.setBackground(white);
btnY.setBounds(275, 60, 45, 45);
contentPane.add(btnY);
btnU = new JButton("U");
btnU.setVerticalAlignment(SwingConstants.TOP);
btnU.setHorizontalAlignment(SwingConstants.LEADING);
btnU.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnU.setBackground(white);
btnU.setBounds(330, 60, 45, 45);
contentPane.add(btnU);
btnI = new JButton("I");
btnI.setVerticalAlignment(SwingConstants.TOP);
btnI.setHorizontalAlignment(SwingConstants.LEADING);
btnI.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnI.setBackground(white);
btnI.setBounds(385, 60, 45, 45);
contentPane.add(btnI);
btnO = new JButton("O");
btnO.setVerticalAlignment(SwingConstants.TOP);
btnO.setHorizontalAlignment(SwingConstants.LEADING);
btnO.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnO.setBackground(white);
btnO.setBounds(440, 60, 46, 45);
contentPane.add(btnO);
btnP = new JButton("P");
btnP.setVerticalAlignment(SwingConstants.TOP);
btnP.setHorizontalAlignment(SwingConstants.LEADING);
btnP.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnP.setBackground(white);
btnP.setBounds(495, 60, 45, 45);
contentPane.add(btnP);
btnA = new JButton("A");
btnA.setVerticalAlignment(SwingConstants.TOP);
btnA.setHorizontalAlignment(SwingConstants.LEADING);
btnA.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnA.setBackground(white);
btnA.setBounds(23, 125, 45, 45);
contentPane.add(btnA);
btnS = new JButton("S");
btnS.setVerticalAlignment(SwingConstants.TOP);
btnS.setHorizontalAlignment(SwingConstants.LEADING);
btnS.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnS.setBackground(white);
btnS.setBounds(82, 125, 45, 45);
contentPane.add(btnS);
btnG = new JButton("G");
btnG.setVerticalAlignment(SwingConstants.TOP);
btnG.setHorizontalAlignment(SwingConstants.LEADING);
btnG.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnG.setBackground(white);
btnG.setBounds(251, 125, 45, 45);
contentPane.add(btnG);
btnH = new JButton("H");
btnH.setVerticalAlignment(SwingConstants.TOP);
btnH.setHorizontalAlignment(SwingConstants.LEADING);
btnH.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnH.setBackground(white);
btnH.setBounds(306, 125, 45, 45);
contentPane.add(btnH);
btnJ = new JButton("J");
btnJ.setVerticalAlignment(SwingConstants.TOP);
btnJ.setHorizontalAlignment(SwingConstants.LEADING);
btnJ.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnJ.setBackground(white);
btnJ.setBounds(361, 125, 45, 45);
contentPane.add(btnJ);
btnK = new JButton("K");
btnK.setVerticalAlignment(SwingConstants.TOP);
btnK.setHorizontalAlignment(SwingConstants.LEADING);
btnK.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnK.setBackground(white);
btnK.setBounds(416, 125, 47, 45);
contentPane.add(btnK);
btnL = new JButton("L");
btnL.setVerticalAlignment(SwingConstants.TOP);
btnL.setHorizontalAlignment(SwingConstants.LEADING);
btnL.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnL.setBackground(white);
btnL.setBounds(471, 125, 45, 45);
contentPane.add(btnL);
btnZ = new JButton("Z");
btnZ.setVerticalAlignment(SwingConstants.TOP);
btnZ.setHorizontalAlignment(SwingConstants.LEADING);
btnZ.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnZ.setBackground(white);
btnZ.setBounds(39, 190, 45, 45);
contentPane.add(btnZ);
btnX = new JButton("X");
btnX.setVerticalAlignment(SwingConstants.TOP);
btnX.setHorizontalAlignment(SwingConstants.LEADING);
btnX.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnX.setBackground(white);
btnX.setBounds(107, 190, 45, 45);
contentPane.add(btnX);
btnC = new JButton("C");
btnC.setVerticalAlignment(SwingConstants.TOP);
btnC.setHorizontalAlignment(SwingConstants.LEADING);
btnC.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnC.setBackground(white);
btnC.setBounds(178, 190, 45, 45);
contentPane.add(btnC);
btnV = new JButton("V");
btnV.setVerticalAlignment(SwingConstants.TOP);
btnV.setHorizontalAlignment(SwingConstants.LEADING);
btnV.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnV.setBackground(white);
btnV.setBounds(250, 190, 45, 45);
contentPane.add(btnV);
btnB = new JButton("B");
btnB.setVerticalAlignment(SwingConstants.TOP);
btnB.setHorizontalAlignment(SwingConstants.LEADING);
btnB.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnB.setBackground(white);
btnB.setBounds(315, 190, 45, 45);
contentPane.add(btnB);
btnN = new JButton("N");
btnN.setVerticalAlignment(SwingConstants.TOP);
btnN.setHorizontalAlignment(SwingConstants.LEADING);
btnN.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnN.setBackground(white);
btnN.setBounds(382, 190, 47, 45);
contentPane.add(btnN);
btnM = new JButton("M");
btnM.setVerticalAlignment(SwingConstants.TOP);
btnM.setHorizontalAlignment(SwingConstants.LEADING);
btnM.setFont(new Font("Times New Roman", Font.PLAIN, 16));
btnM.setBackground(white);
btnM.setBounds(449, 190, 48, 45);
contentPane.add(btnM);
/**
* 创建面板panel置于面板contentPane中,设置面板panel的位置、宽高、TitledBorder、背景色以及布局方式(边界布局)
*/
JPanel panel = new JPanel();
panel.setBorder(new TitledBorder(null, "文本显示区", TitledBorder.LEADING, TitledBorder.TOP, null, null));
panel.setBackground(Color.WHITE);
panel.setBounds(0, 0, 540, 45);
contentPane.add(panel);
panel.setLayout(new BorderLayout(0, 0));
/**
* 创建文本框textField置于面板panel的中间
*/
textField = new JTextField();
textField.addKeyListener(new KeyAdapter() { //文本框添加键盘事件的监听
char word;
@Override
public void keyPressed(KeyEvent e) { //按键被按下时被触发
word=e.getKeyChar();//获取按下键表示的字符
for(int i=0;i<btns.size();i++){//遍历存储按键ID的ArrayList集合
//判断按键是否与遍历到的按键的文本相同
if(String.valueOf(word).equalsIgnoreCase(btns.get(i).getText())){
btns.get(i).setBackground(green);//将指定按键颜色设置为绿色
}
}
}
@Override
public void keyReleased(KeyEvent e) { //按键被释放时被触发
word=e.getKeyChar();//获取释放键表示的字符
for(int i=0;i<btns.size();i++){//遍历存储按键ID的ArrayList集合
//判断按键是否与遍历到的按键的文本相同
if(String.valueOf(word).equalsIgnoreCase(btns.get(i).getText())){
btns.get(i).setBackground(white);//将指定按键颜色设置为白色
}
}
}
});
panel.add(textField, BorderLayout.CENTER);
textField.setColumns(10);
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# 多线程
---
## 一、线程简介
* Java 语言提供了并发机制,程序员可以在程序中执行多个线程,每一个线程完成一个功能,并与其他线程并发执行,这种机制称之为多线程。
* Windows 操作系统是多任务操作系统,以进程为单位;一个进程就是一个包含自身地址的程序,每个独立的程序都称为进程,如正在运行 Typora;每个进程中都可以同时包含多个线程。
* 系统可以分配给每个进程一段有限的使用 CPU 的时间(CPU 时间片),CPU 在这段时间中执行某个进程;同理,进程里的每一个线程都可以分配到一小段执行时间,基于此,一个进程可以具有多个并发执行的线程;然后下一个时间片有跳至另一个进程执行。由于 CPU 转换较快,所以使得每个进程好像在同时执行一样。
* Windows 操作系统的执行模式如下图:
![](D:\编程笔记\java\多线程在 windows 中的执行模式.jpg)
## 二、实现线程的两种方式
* Java 中主要提供两种方式实现多线程,分别为继承 java.lang.Thread 类与实现 java.lang.Runnable 接口。
### 1、继承 Thread 类
* Thread 类是 java.lang 包中的一个类,从这个类中实例化的对象代表线程。
* 通过继承 Thread 类创建并执行一个线程的步骤如下:
1)创建一个继承自 Tread 类的子类。
2)覆写 Thread 类的 run 方法。
3)创建线程类的一个对象。
4)通过线程类的对象调用 start 方法启动线程,之后会自动调用覆写的 run 方法执行线程。
* Thread 类常用构造方法如下:
1)public Thread():创建一个新的线程对象。
2)public Thread(String threadName):创建一个名称为 threadName 的线程对象。
* 继承 Thread 类创建一个新的线程的语法如下:
```java
public class ThreadTest extends Thread {}
```
* Thread 类常用方法如下表:
| 方法 | 说明 |
| ---------------------------- | ------------------------------------------------------------ |
| interrupt() | 中断线程 |
| join() | 等待该线程终止 |
| join(long millis) | 等待该线程终止的时间最长为 millis 毫秒 |
| run() | 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法,否则,该方法不执行任何操作并返回 |
| setPriority(int newPriority) | 更改线程的优先级 |
| sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行) |
| start() | 使该线程开始执行; Java 虚拟机调用该线程的 run 方法 |
| yield() | 暂停当前正在执行的线程对象,并执行其他线程。 |
* 完成线程真正的功能的代码放在类的 run 方法里。run 方法必须使用以下格式:
```java
public void run() {}
```
* 如果 start 启动一个已经启动的线程,系统将会抛出 IllegalThreadStateException 异常。
* 实例:
```java
public class ThreadTest extends Thread{
private int count = 10;
public void run() {
do {
System.out.print( count + " " );
--count;
} while (count != 0);
}
public static void main(String[] args) {
ThreadTest test = new ThreadTest();
test.start(); // 启动线程
}
}
/* 输出如下:
10 9 8 7 6 5 4 3 2 1
*/
```
### 2、实现 Runnable 接口
* 当需要继承非 Thread 类,又要实现多线程,便可以使用 Runnable 接口来实现,例如 一个拓展 JFrame 的 GUI 程序不可能再继承 Thread 类,因为 Java 语言不支持多继承。
* 实现 Runnable 接口的语法如下:
```java
public class Thread extends Object implements Runnable
```
* **实质上,Thread 类实现了 Runnable 接口,其中的 run() 方法正是对 Runnable 接口中的 run() 方法的具体实现。**
* Runnable 接口启动新的线程的步骤如下:
1)建立 Runnable 对象。
2)使用参数为 Runnable 对象的构造方法创建 Thread 实例。
3)调用 start() 方法启动线程。
* 通过 Runnable 接口创建线程,首先得编写一个实现 Runnable 接口的类,接着实例化。
* 例子:
```java
import java.awt.Container;
import java.net.URL;
import javax.swing.*;
public class SwingAndThread extends JFrame{
private JLabel jl = new JLabel( );
private int count = 0; // 声明计数变量
private Container container;
{
container = getContentPane();
}
private SwingAndThread() {
setBounds( 300,200,250,100 );
container.setLayout( null ); // 使用绝对布局
try {
URL url = SwingAndThread.class.getResource( "1.gif" );
Icon icon = new ImageIcon( url );
jl.setIcon( icon );
} catch (NullPointerException ex) {
System.out.println( "图片不存在!!" );
}
jl.setHorizontalAlignment( SwingConstants.LEFT );
jl.setBounds( 10,10,200,50 );
jl.setOpaque( true );
// 声明线程对象
Thread t = new Thread( new Roll() );
t.start();
container.add(jl);
setVisible( true );
setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
}
class Roll implements Runnable {
Roll() {
}
@Override
public final void run() {
while (count <= 200) {
// 将标签的横坐标用变量表示
jl.setBounds( count,10,200,50 );
try {
Thread.sleep( 1000 ); // 为了体现滚动效果,使线程休眠 1000 毫秒
} catch (Exception e) {
e.printStackTrace();
}
count += 4;
if (count == 200) {
// 当图标到达标签最右边时,使其回到标签最左边
count = 10;
}
}
}
}
public static void main(String[] args) {
new SwingAndThread();
}
}
```
* 运行效果:
![](D:\编程笔记\java\SwingAndThread.jpg)
## 三、线程的生命周期
* 线程具有生命周期,有五种状态:出生状态、就绪状态、运行状态、暂停状态(包括休眠、等待和阻塞等)和死亡状态。
* 五种状态之间的关系如下图:
![](D:\编程笔记\java\线程生命周期.jpg)
## 四、操作线程的方法
* 操作线程的方法有很多种,这些方法都可以使线程从某一种状态到另一种状态。
### 1、线程的休眠
* 让线程休眠的方法是 sleep(),其参数为指定线程休眠的时间,sleep() 方法通常在 run() 的内循环中使用。
* 使用例子:
```java
try{
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
```
* 实例:
```java
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public class SleepMethodTest extends JFrame {
private static final long serialVersionUID = 1L;
private Thread t;
private static Color[] color = { Color.BLACK, Color.BLUE,Color.CYAN,Color.GREEN, Color.ORANGE,Color.YELLOW};
private static final Random rand = new Random( ); // 创建随机对象
private static Color getC() { // 获取随机颜色值的方法
// 随机产生一个color数组长度
return color[rand.nextInt( color.length )];
}
private SleepMethodTest() {
t = new Thread( new Draw() ); // 创建匿名线程对象
t.start();
}
class Draw implements Runnable { // 定义内部类,用来在窗体中绘制线条
int x = 30; // 定义初识坐标
int y = 50;
@Override
public void run() { // 重写线程接口方法
while(true) {
try {
Thread.sleep( 100 ); //线程休眠0.1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// 获取绘图组件上下文对象
Graphics graphics = getGraphics();
graphics.setColor( getC() ); // 设置绘图颜色
// 绘制直线并递增垂直坐标
graphics.drawLine( x,y,100, y );
y++;
if(y >= 80) {
y = 50;
}
}
}
}
// 初识化程序界面
public static void init(JFrame frame, int width, int height) {
frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
frame.setSize( width,height );
frame.setVisible( true );
}
public static void main(String[] args) {
init(new SleepMethodTest(),100,100);
}
}
```
* 运行效果如下图:
![](D:\编程笔记\java\Sleep.jpg)
### 2、线程的加入
* 假如存在一个线程A,现在需要插入线程B,并且要求线程B先执行完毕,再执行线程A;对于此种操作可以使用 Thread 类中的 join() 方法来完成。
* 当某个线程使用 join() 方法加入另一个线程时,另一个线程会等待该线程执行完毕后再继续执行。
* 例子:
```java
import javax.swing.*;
import java.awt.*;
public class JoinTest extends JFrame {
private Thread threadB;
private JoinTest() {
super();
setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
setSize( 100, 100 );
setVisible( true );
// 将进度条设置在窗体最北面
// 定义两个进度条组件
JProgressBar progressBar = new JProgressBar();
getContentPane().add( progressBar, BorderLayout.NORTH );
// 将另一条进度条放置在窗体最南面
JProgressBar progressBar2 = new JProgressBar();
getContentPane().add( progressBar2, BorderLayout.SOUTH );
// 设置进度条显示数字
progressBar.setStringPainted( true );
progressBar2.setStringPainted( true );
//使用匿名内部类初始化 Thread 实例
// 定义两个线程
Thread threadA = new Thread( new Runnable() {
int count = 0;
@Override
public void run() {
while (true) {
++count;
progressBar.setValue( count );
try {
Thread.sleep( 100 );
if (count == 20) {
threadB.join();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
} );
threadA.start();
threadB = new Thread( new Runnable() {
int count = 0;
@Override
public void run() {
do {
++count;
progressBar2.setValue( count );
try {
Thread.sleep( 100 );
} catch (Exception e) {
e.printStackTrace();
}
} while (count != 100);
}
} );
threadB.start();
}
public static void main(String[] args) {
new JoinTest();
}
}
```
* 运行效果如下图:
![](D:\编程笔记\java\JoinTest.jpg)
### 3、线程的中断
* 在 run 中使用无线循环的形式,然后使用一个布尔型标记,来控制循环的停止。例如下面这个例子:
```java
public class InterruptedTest implements Runable{
private boolean isContinue = false;//设置一个标记,默认值为 false
public void run() {
while(true){
//....
if( isContinue) //当isContinue 变为 true 时,停止线程
break;
}
}
public void setContinue() { // 定义设置 isContinue 变量为 true 的方法
this.isContinue = true;
}
}
```
* 实例:
```java
import javax.swing.*;
import java.awt.*;
public class InterruptedSwing extends JFrame {
private InterruptedSwing(){
setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE );
setSize(100,100);
setVisible( true );
final JProgressBar progressBar = new JProgressBar( ); // 创建进度条
// 将进度条放置到合适的位置
getContentPane().add(progressBar, BorderLayout.NORTH );
progressBar.setStringPainted( true ); // 设置进度条上显示数字
// 执行线程停止方法
Thread thread = new Thread() {
int count = 0;
public void run() {
while (true) {
++count;
progressBar.setValue( count );
try {
if (count == 30) {
interrupt(); // 执行线程停止方法
}
Thread.sleep( 100 );
} catch (InterruptedException e) {
System.out.println( "当前线程被中断" );
break;
}
}
}
};
thread.start();
}
public static void main(String[] args) {
new InterruptedSwing();
}
}
```
\ No newline at end of file
此差异已折叠。
# 集合类
---
## 一、集合类概述
* 集合类又称为容器,类似数组,不同的是集合的长度并不固定,且是用来存放对象的引用;常用的集合有 List 集合、Set 集合和 Map 集合;其中前两者从 Collection 接口继承而来。
## 二、Collection 接口
* Collection 接口是层次结构中的根接口,构成 Collection 的单位称为元素;Collection 接口不能直接使用,但是通过 List 接口和 Set 接口可以使用 Collection 的添加元素、删除元素和管理数据的方法。
* Collection 接口的常用方法:
| 方法 | 功能描述 |
| :--------------: | :----------------------------------------------------------- |
| add(Object e) | 将指定的对象添加到该集合中 |
| remove(Object o) | 将指定的对象从该集合中移除 |
| isEmpty() | 返回 boolean 值,用于判断当前集合是否为空 |
| iterator() | 返回在此 Collection 的元素上进行迭代的迭代器,用于遍历集合中的对象 |
| size() | 返回 int 型值,获取该集合中的元素个数 |
## 三、List 集合
* List 集合包括 List 接口以及 List 接口的所有实现类。List 集合允许使用索引来访问集合中的元素。
### 1、List 接口
* List 接口除了继承 Collection 的方法外,还自定义了以下两个重要的方法:
| 方法 | 功能描述 |
| -------------------------- | ------------------------------------------ |
| get(int index) | 获取指定索引位置的元素 |
| set(int index, Object obj) | 将集合中指定索引位置的对象修改为指定的对象 |
### 2、List 接口的实现类
* List 接口的实现类有两个:ArrayList 和LinkedList。前者采用顺序存储结构后者采用链式存储结构;所以 ArrayList 和 LinkedList的优缺点就如数据结构中的顺序表和链表一样。
* 这两种结构的 List 对象的声明语法如下:
```java
List<E> list = new ArrayList<>();
List<E> list2 = new LinkedList<>();
E 代表 Java 中的泛型
//例子:
import java.util.*;
public class ListTest {
public static void main(String[] args) {
List<String> list = new ArrayList<>(); //创建集合对象
//向集合中添加元素
list.add("A");
list.add("B");
list.add("C");
int i = (int)(Math.random()*list.size()); //获得0~2之间的随机数
System.out.println("随机获取数组中的元素:"+list.get(i));
list.remove(2); //移除集合中指定索引位置的元素
System.out.println("将索引2的元素移除后,数组中的元素是:");
for(int j=0;j<list.size();j++){
System.out.println(list.get(j));
}
}
}
//输出:
随机获取数组中的元素C
将索引2的元素移除后数组中的元素是
A
B
```
### 3、Iterator 迭代器
* Iterator 专门用于对集合中的元素进行迭代的迭代器。Iterator 迭代器常用的方法如下表:
| 方法 | 功能描述 |
| --------- | ------------------------------------------------------------ |
| hasNext() | 如果仍有元素可以迭代,则返回true |
| next() | 返回迭代的下一个元素 |
| remove() | 从迭代器指向的 Collection 中移除迭代器返回的最后一个元素(可选操作) |
* 示例:
```java
import java.util.*;
public class IteratorTest {
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
Iterator<String> it = list.iterator();
while(it.hasNext()){
String str = (String)it.next();
System.out.println(str);
}
}
}
//输出
A
B
C
```
## 四、Set 集合
* Set 集合中的对象不按特定的方式排序,只是简单的把对象加入集合中,但 Set 集合中不能包含重复对象。Set 集合由 Set 接口和 Set 接口的实现类组成。
### 1、Set 接口的实现类
* Set 接口常用的实现类有 HashSet 类和 TreeSet 类。
#### 1.1、HashSet 类
* HashSet 主要依据哈希算法直接将元素指定到一个地址上。当向 HashSet 中添加元素时,会调用 equals 方法判断是否有重复元素;判断是通过比较它们的 HashCode 来进行。HashSet 集合中常用的方法都是重写了 Set 接口中的方法;此集合允许 null。
#### 1.2、TreeSet 类
* TreeSet 类实现 Set 接口的基础上,实现了 java.util.SortedSet 接口;TreeSet 类实现的 Set 集合在遍历时按照自然顺序递增排序,也可以自定义排序规则;TreeSet 集合不允许 null 。
* TreeSet 类新增方法如下表:
| 方法 | 功能描述 |
| ---------------------------------- | ------------------------------------------------------------ |
| first() | 返回此 Set 中当前的第一个(最低)元素 |
| last() | 返回此 Set 中当前最后一个(最高)元素 |
| comparator() | 返回对此 Set 中的元素进行排序的比较器。如果此 Set 使用自然顺序,则返回 null |
| headSet(E toElement) | 返回一个新的 Set 集合,新集合是 toElement (不包含)之前的所有对象 |
| subSet(E fromElement, E toElement) | 返回一个新的 Set 集合,是 fromElement(包含)对象与 toElement(不包含)对象之间的所有对象 |
| tailSet(E fromElement) | 返回一个新的 Set 集合,新集合包含对象 fromElement(包含)之后的所有对象。 |
* 示例:
```java
import java.util.*;
public class HashSetTest {
public static void main(String[] args) {
Set set = new HashSet(); //创建Set 集合
set.add("c");
set.add("c");
set.add("a");
set.add("b");
Iterator<String> it; //创建迭代器
it = set.iterator();
while(it.hasNext()){ //遍历 HashSet 集合
String str = (String)it.next(); //获取集合中的元素
System.out.println(str);
}
}
}
//输出
a
b
c
```
## 五、Map 集合
* Map 接口,提供了 key 到 value 的映射,Map 中不能包含相同的 key,每个 key 只能映射一个 value;key 中决定了存储对象的存储位置,通过一种“散列技术”,产生一个散裂码的数值来确定存储对象的存储位置。Map 集合包含 Map 接口和 Map 接口的实现类。
### 1、Map 接口
* Map 接口的常用方法如下:
| 方 法 | 功 能 描 述 |
| :----------------------------: | :----------------------------------------------------------: |
| put(Object key, Object value) | 向集合中添加指定的 key 与 value 的映射关系 |
| containsKey(Object key) | 如果此映射包含指定 key 的映射关系,则返回true |
| containsValue(Object value) | 如果此映射将一个或多个 key 映射到指定值,则返回 true |
| get(Object key) | 如果存在指定的 key 对象,则返回该对象对应的值,否则返回 null |
| keySet() | 返回该集合中所有 key 对象形成的 Set 集合 |
| values() | 返回该集合中所有值对象形成的 Collection 集合 |
### 2、Map 接口的实现类
* Map 接口的实现类有 HashMap 和 TreeMap 两种:
#### 2.1、HashMap
* HashMap 类是基于哈希表的 Map 接口的实现,此实现提供所有可选的映射操作,允许使用 null 值和 null 键,但必须保证键的唯一性;HashMap 通过哈希表对其内部的映射关系进行快速查找;此类不保证映射的顺序,特别是不保证该顺序的恒久不变。
#### 2.2、TreeMap
* TreeMap 同样实现了 java.util.SortedMap 接口;TreeMap 中的映射关系具有一定的顺序;在添加、删除和定位映射关系的操作上,TreeMap 的性能比 HashMap 的差;TreeMap 不允许健对象是 null。
* 示例:
```java
import java.util.*;
public class HashMapTest {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>(); //创建Map对象
map.put("ISBN-978654", "Java从入门到精通"); //添加对象
map.put("ISBN-978361", "Android 从入门到精通");
map.put("ISBN-978893", "21天学Andorid");
map.put("ISBN-978756", "21天学Java");
Set<String> set = map.keySet(); //构建键集合
Collection<String> coll = map.values(); //构建值集合
Iterator<String> it1,it2; //创建键值迭代器
it1 = set.iterator();
it2 = coll.iterator();
System.out.println("key值\tvalue值");
while(it1.hasNext()&&it2.hasNext()){
System.out.println(it1.next()+"\t"+it2.next()); //遍历对象
}
}
}
//输出
key值 value值
ISBN-978756 21天学Java
ISBN-978654 Java从入门到精通
ISBN-978893 21天学Andorid
ISBN-978361 Android 从入门到精通
```
* 构造 TreeMap 对象:
```java
System.out.println("===================================\n\tTreeMap traver:");
TreeMap<String, String> treemap = new TreeMap<>(); // 创建TreeMap 对象
treemap.putAll(map); // 向集合添加元素
Iterator<String> iter = treemap.keySet().iterator();
while (iter.hasNext()) {
String str = (String) iter.next();
String name = (String) treemap.get(str);
System.out.println(str + ":" + name);
}
//输出:
===================================
TreeMap traver:
ISBN-978361:Android 从入门到精通
ISBN-978654:Java从入门到精通
ISBN-978756:21天学Java
ISBN-978893:21天学Andorid
```
## 六、集合的使用场合
### 1、List 集合
* List 集合关注的是索引,其元素是顺序存放的,例如学生成绩,成绩可以重复,此时就可以使用List集合。
### 2、Set 集合
* Set 集合关注唯一性,不允许有重复值,例如学生学号,学号必须唯一,此时就可以使用 Set 集合。
### 3、Map 集合
* Map 集合关注唯一标识符(KEY),将唯一的键映射到某个元素,例如每个学生学号与姓名的映射。一个学号对应一个学生姓名,学号不能重复,但是学生姓名有可能重复,此时就可以使用 Map 集合。
\ No newline at end of file
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册