Java中多线程的实现

    简单地说,线程就是程序中独立的运行片段,一个程序就是一个进程,而一个进程里面一般不会只有一个线程,多数情况是多条路线同时执行。

 

    之前写的东西,画板也好,五子棋也好,都是单线程的,就是说一个程序里面从头到尾都只有一个线程,即执行顺序,只能执行完上一句才能继续下一句。

 

    但是现实生活中显然不是这样的,一种事物或现象的出现肯定是多个因素同时影响的结果,既然面向对象是模拟现实,自然一个程序的运行结果也要有几个不同线程来共同实现。

 

    在Java中实现多线程的两种方法:

    1、创建一个类去继承Thread类,重写Thread类中的run方法。

    2、创建一个类实现Runnable 接口,实现接口中的run方法。在创建新的线程对象的时候,通过构造方法传入这个类的对象。

 

    不管是哪种方法,线程所执行的操作都是run方法里面的内容。

 

    我们要实现多线程需要的操作一般有三步:

    1、定义线程中的run方法里的内容,即线程的执行语句。

    2、建立用户线程实例。

    3、启动线程,调用线程对象的start方法。

 

以下是用线程实现的弹球游戏。

 

package 线程;

public interface Config {

	  final static int SIZE = 50;
	  final static int X = 20;
	  final static int Y = 20;
}

 

主线程:

package 线程;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class XianCheng {

	private	JPanel jp2;
	private ArrayList<MyThread> list = new ArrayList();
	
	public static void main(String[] args) {
		XianCheng xc = new XianCheng();
		xc.initUI();
	}

	public  void initUI(){
		
		//实例化窗体、面板、按钮...
		JFrame jf = new JFrame("线程-------------------");
		JPanel jp1 = new JPanel();
		jp2 = new JPanel();
	        JButton jb1 = new  JButton("Start");
	        JButton jb2 = new JButton("Pause");
	        JButton jb3 = new JButton("Resume");
	        JButton jb4 = new JButton("Stop");
	    
	    //设置窗体大小
		jf.setSize(700,700);
		//设置关闭窗体时退出程序
		jf.setDefaultCloseOperation(3);
		//设置窗体居中显示
		jf.setLocationRelativeTo(null);
		
		//实例化监听器对象,直接传入窗体对象,而不是画布
		MyListener l = new MyListener(jp2);
		//获取到队列
		list = l.getList();
		
		//添加监听器
		jb1.addActionListener(l);
		jb2.addActionListener(l);
		jb3.addActionListener(l);
		jb4.addActionListener(l);
		
		//把按钮添加到面板上
		jp1.add(jb1);
		jp1.add(jb2);
		jp1.add(jb3);
		jp1.add(jb4);
		//把面板添加到窗体上
		jf.add(jp1,BorderLayout.NORTH);
		jf.add(jp2,BorderLayout.CENTER);
		
		//设置窗体可见
		jf.setVisible(true);
		
		//获取面板上的画布对象
		Graphics  g = jp2.getGraphics();
		
		//实例化图片对象
		ImageIcon ima = new ImageIcon("Imas/bj.jpg");
		
		//图片坐标
		int x =  0;
		int y =  0; 
		//图片移动速度
		int yy = 0;
		int	vy = 0;
		//图片移动加速度
		int addvy = 1;
		
		while(true){
			
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			//创建缓冲图片对象
			BufferedImage buffer = new   BufferedImage(jp2.getWidth(),jp2.getHeight(),
					BufferedImage.TYPE_INT_RGB);
			//获取到缓冲图片对象中的画布
			Graphics g2 = buffer.getGraphics();
			//将背景图画到缓冲图片上
			g2.drawImage(ima.getImage(), 0, 0, null);
			
			//取出队列中的ball对象,调用画球的方法
			for(int i =0; i<list.size() ;i++){
				MyThread ball = list.get(i);
				ball.DrawBall(g2);
			}
			
			//这里画两张图的目的是在图片移动的时候两张图有衔接
			g.drawImage(buffer, x, y, null);
			g.drawImage(buffer, x+buffer.getWidth(), y, null);
			x--;
			if(x+buffer.getWidth()<0){
				x=0;
			}
			
		}
	}
	
}

 

 监听器:

package 线程;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.*;

public class MyListener implements ActionListener{

	private  JPanel jp;
	private ArrayList<MyThread> list = new ArrayList();
	
	//构造方法,传入要画图的面板
	public MyListener(JPanel jp){
		this.jp = jp;
	}
	//获取队列的方法
	public ArrayList  getList(){
		return list;
		
	}
	//点击按钮的处理方法
	public void actionPerformed(ActionEvent e) {
		//获取按钮的文本值
		String s =e.getActionCommand();
		
		//如果点击Start按钮
		if(s.equals("Start")){
			MyThread m1 = new MyThread(jp,list);
			m1.start();
			list.add(m1);
		}
		//如果点击Pause按钮
		if(s.equals("Pause")){
			//循环遍历队列取出队列中的对象,设置暂停标志位为true
			for(int i = 0 ;i<list.size();i++){
				MyThread m1 = list.get(i);
				m1.setPauseFlag(true);
			}
		}
		//如果点击Resume按钮
		if(s.equals("Resume")){
			//循环遍历队列取出队列中的对象,设置暂停标志位为false
			for(int i = 0 ;i<list.size();i++){
				MyThread m1 = list.get(i);
				m1.setPauseFlag(false);
			}
		}
		//如果点击Stop按钮
		if(s.equals("Stop")){
			//把队列中的对象全部清空
			while(!list.isEmpty()){
				list.remove(0);
			}
		}
}

 

画球的线程:

package 线程;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MyThread extends Thread {
	
	private JPanel jp;
	private int X,Y,R;//坐标、半径
	private int change_x,change_y;//速度
	private Color color;
	private Graphics2D g;
	//暂停和停止的标志位
	private boolean pauseFlag = false,stopFlag = false;
	//存放小球对象的队列
	private ArrayList<MyThread> list;
	//记录小球撞击之前的坐标
	private int oldx,oldy;

	public MyThread(JPanel jp,ArrayList<MyThread> list){
		
		//属性初始化
		this.jp = jp;
		this.list = list;
		
		Random r = new Random();
		//给速度、半径和颜色随机赋值
		change_x = r.nextInt(2)+1;
		change_y = r.nextInt(2)+1;
		R = r.nextInt(40)+20;
		color = new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256));

		X = R;
		Y = R;
	}
	
	public void run(){
		    //设置为一直循环
			while(true){
				//每次循环休眠5毫秒
				try {
					Thread.sleep(5);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				//判断是否停止,如果停止了就返回
				if(stopFlag){
					return;
				}
				//判断是否暂停,如果暂停就不执行下面的代码
				if(pauseFlag){
					continue;
				}
				//调用改变坐标的方法
				changeXY();
			}
	}
	//判断坐标,改变速度
	public void changeXY(){
		//记录原来的坐标,小球撞击时不会粘在一起
		oldx = X;
		oldy = Y;
		//先改变坐标
		X+=change_x;
		Y+=change_y;
		//调用check方法,判断小球之间是否撞击
		check();
		
		//如果小球运动到边界则改变方向
		if(X+R>jp.getWidth()){
			change_x = -change_x;
		}
		if(X-R<0){
			change_x = Math.abs(change_x);
		}
		if(Y+R>jp.getHeight()){
			change_y = -change_y;
		}
		if(Y-R<0){
			change_y = Math.abs(change_y);
		}
	}
	
	//暂停
	public void setPauseFlag(boolean b){
		pauseFlag = b;
	}
	//停止
	public void setStopFlag(boolean b){
		stopFlag = b;
	}
	
	//画球的方法
	public void DrawBall(Graphics g){
		
		int red = color.getRed();
		int green = color.getGreen();
		int bule = color.getBlue();
		int xx = X;
		int yy = Y;
		int rr = R;
		//利用循环画出立体效果的圆
		for(int i = 0 ;i<50;i++){
			red+=4;
			green+=4;
			bule+=4;
			if(red>255)
				red=255;
			if(green>255)
				green=255;
			if(bule>255)
				bule=255;
				
			Color c= new Color(red,green,bule);
			g.setColor(c);
			g.fillOval(xx-rr,yy-rr, rr*2 ,rr*2);
			xx+=1;
			yy+=1;
			rr-=2;
		}
	}			
	//判断小球之间是否碰撞
	public boolean check(){
		
		for(int i = 0;i<list.size();i++){
			//利用循环取出队列中的对象
			MyThread b = list.get(i);
			//如果是它本身就不需要判断
			if(b == this)
				continue;
			//利用勾股定理
			int x0 = b.X - this.X;
			int y0 = b.Y - this.Y;
			int r0 = b.R + this.R;
			//算出两球之间的距离
			int distence = (int) Math.sqrt(x0*x0+y0*y0);
			
			//如果距离小于半径之和就代表相撞
			if(distence < r0){
				//互相交换水平速度
				int temp_x = this.change_x;
				this.change_x = b.change_x;
				b.change_x = temp_x;
				
				//互相交换竖直速度
				int temp_y = this.change_y;
				this.change_y = b.change_y;
				b.change_y = temp_y;
				
				X = oldx;
				Y = oldy;
				return true;
			}
		}
		return false;
	}	
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值