一、进程和线程
进程是指一个内存中运行的应用程序,而线程是指进程中的一个执行流程。
一个程序有一个或者多个进程,一个进程有一个或者多个线程。
电脑的8个CPU可同时处理3000多个线程,CPU执行的速度的很快,在执行中不断的切换,看起来像是在同时处理。
二、线程的创建
在 Java程序中,有两种方法创建线程:
1.对 Thread 类进行派生并覆盖 run方法,例:
public class 线程名 extends java.lang.Thread{
//重写run方法
public void run(){
}
}
2.通过实现Runnable接口创建,例:
public class 线程名 implements Runnable {
//重写run方法
public void run(){
}
}
三、线程的使用
写一个枫叶落下的效果,每点击一下按钮或页面则会产生一个线程,生成一个下落的枫叶。
首先,创建JFrame添加背景按钮等
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class UI extends JFrame{
Color color1 = new Color(106,163,216);
Color color2 = new Color(233,218,144);
Color color3 = new Color(180,180,180);
Font font1 = new Font("华文中魏",Font.BOLD,30);
public void showUI() {
this.setTitle("落叶");
this.setSize(1200,800);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
this.setLocationRelativeTo(null);
Listener lis = new Listener();
JButton but1 = new JButton("枫叶");
but1.setFont(font1);
but1.setPreferredSize(new Dimension(100,50));
but1.setBackground(color2);
but1.addActionListener(lis);
JPanel buttonPanel = new JPanel();
buttonPanel.setPreferredSize(new Dimension(0,60));
this.add(buttonPanel,BorderLayout.NORTH);
buttonPanel.setVisible(true);
buttonPanel.setBackground(color3);
JPanel showPanel = new JPanel();
this.add(showPanel,BorderLayout.CENTER);
showPanel.addMouseListener(lis);
buttonPanel.add(but1);
this.setVisible(true);
Graphics g = showPanel.getGraphics();
lis.g = g;
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(color1);
g.fillRect(0,112,this.getWidth(),this.getHeight());
}
public static void main (String[] args) {
UI ui = new UI();
ui.showUI();
}
}
动作监听器和鼠标监听器代码,每次点击新建一个线程来控制新的枫叶。点击按钮,在上方随机位置生成枫叶,点击其他位置则在点击位置生成枫叶。
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Listener implements ActionListener,MouseListener {
Graphics g;
int x,y;
public void actionPerformed(ActionEvent e) {
java.util.Random ran=new java.util.Random();
int x=ran.nextInt(1200);
int y=0;
DrawThread dt=new DrawThread(g,x,y);
dt.start();//启动线程,调用start
//System.out.println("己启动一个线程画一片落叶");
}
public void mouseClicked(MouseEvent e) {
x=e.getX()-50;
y=e.getY()-50;
DrawThread dt=new DrawThread(g,x,y);
dt.start();
};
public void mousePressed(MouseEvent e) {};
public void mouseReleased(MouseEvent e) {};
public void mouseEntered(MouseEvent e) {};
public void mouseExited(MouseEvent e) {};
}
接下来是线程部分代码,关键部分是重写run方法,注意重写run方法的格式为public void run(){},()中不能加入任何参数。
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class DrawThread extends java.lang.Thread{
private int x,y;
private Graphics g;
JFrame ui;
Color color1 = new Color(106,163,216);
public DrawThread(Graphics g,int x,int y) {
this.g=g;
this.x=x;
this.y=y;
}
public void draw(Graphics g) {
Image image = new ImageIcon("立秋枫叶.png").getImage();
Image image1 = new ImageIcon("蓝色.png").getImage();
for(int i=0;i<1000;i++){
g.drawImage(image,x,y+i,100,100,null);
//每画一个,停一下
try{
Thread.sleep(60);
}catch(Exception ef){}
g.drawImage(image1,x,y+i,100,100,null);
}
}
//重写run方法
public void run(){
draw(g);
}
}
以下是枫叶下落的效果图:
上传png图片,不知道下载之后还是不是透明背景。
四、volatile关键字
volatile关键字可以使一个变量在多个线程中可见,也就是当一个线程修改了某个变量的值,这新值对其他线程来说立即可见。
这主要是因为:使用volatile关键字,会强制将修改的值立即写入主存,并且让缓存行无效,然后其他线程去读就会读到新的值。