一、线程、进程、程序
进程:按照百度的说法,进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体。它不只是程序的代码,还包括当前的活动,通过程序计数器的值和处理寄存器的内容来表示。
也就是一个独立运行的程序。
比如一个正在运行的记事本和一个正在运行的浏览器,这是两个进程。如果启动了两次记事本,那么也得到了两个进程。
线程:线程是通过利用cpu的轮转来让程序中不同的代码同时执行的机制。 反正这句子对我来说读了和没读没多大区别,我的理解是,线程在一个进程中能同时运行多段代码,看上去每个程序好像都在运行,但其实每个时刻只有一个程序在运行。
一、线程、进程、程序的区别
进程:按照百度的说法,进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体。它不只是程序的代码,还包括当前的活动,通过程序计数器的值和处理寄存器的内容来表示。
也就是一个独立运行的程序。
比如一个正在运行的记事本和一个正在运行的浏览器,这是两个进程。如果启动了两次记事本,那么也得到了两个进程。
线程:线程是通过利用cpu的轮转来让程序中不同的代码同时执行的机制。 反正这句子对我来说读了和没读没多大区别,我的理解是,线程在一个进程中能同时运行多段代码,看上去每个程序好像都在运行,但其实
每个时刻只有一个程序在运行。
程序:其实就是一个个的文件。具体的定义暂时不用管。
二、关于线程
可以通过集成Thread类或者Runnable接口编写代码来定义、实例化、启动新的线程。一个Thread类示例只是一个对象,和Javaz中的其他对象一样,具有变量和方法,”生死于堆上“。
一个Java应用总是从main()方法开始执行,它运行在一个线程内,被称为主线程。一旦创建了一个新的线程,就生成了一个新的调用栈。所以又有“伴随线程”(也叫“精灵线程”)的说法。
使用线程的过程大致可以分为,定义,启动,运行,结束的过程。
三、线程的使用
1.定义线程:以继承了Thread类为例。继承之后我们将run()方法进行重写,也就是把希望这个线程做的事情放在run()里面。
2.实例化线程:用定义好的类来new一个线程对象。
如果你用的是Runnable接口这里有点区别,需要使用Thread的构造方法
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(ThreadGroup group, Runnable target)
Thread(ThreadGroup group, Runnable target, String name)
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
3.启动线程:在线程的Thread对象上调用
start()方法,而不是run()或者别的方法。这是因为在start()被调用之前,线程处于新状态,也就是刚刚生成的状态,指的是有一个Thread对象,但还没有一个真正的线程。
start()被调用以后,线程从新状态变为
可运行状态。当该线程获得执行机会的时候,它run()里的方法会自动进行。
注意:对Java来说,run()方法没有任何特别之处。像main()方法一样,它只是新线程知道调用的方法名称(和签名)。因此,在Runnable上或者Thread上调用run方法是合法的。但并不启动新的线程。
四、抽奖系统的实现
下面准备做一个抽奖系统,抽取本年度NBA的MVP(嗯真正的MVP不是抽奖得到的哈哈哈)
思路就是:实现抽奖界面GameJf继承ActionListener接口—>为按钮添加监听,点击时能更换其内容—>创建Lotterythread类继承Thread,重写run()方法—>Over。
首先是界面的代码:
package Game180710;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GameJf extends JFrame implements ActionListener{
private JButton jb=new JButton();
private JLabel lb1=new JLabel("*******");
// public volatile boolean flag; //***
private Lotterythread l;
private String str[]={"Lebron James","James Harden","Steven Curry","Kevin Duant","Ivring","Leonard"};
public static void main(String[] args) {
GameJf JF=new GameJf();
JF.initUI();
}
public void initUI(){
this.setTitle("Who is the MVP? ");
this.setSize(600, 400);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(3);
this.setLayout(new FlowLayout(FlowLayout.CENTER));
JLabel start=new JLabel("MVP is:");
jb.setText("Start");
jb.setPreferredSize(new Dimension(150,100));
jb.addActionListener(this);
lb1.setPreferredSize(new Dimension(200,200));
this.add(start);
this.add(lb1);
this.add(jb);
l=new Lotterythread(lb1);
l.start();
this.setVisible(true);// 设置窗体为可见
}
public void actionPerformed(ActionEvent e) {
if(jb.getText().equals("Start")){
l.flag=true;
//System.out.println(l.flag);
jb.setText("Stop !");
//l.flag=false;
}
else{
l.flag=false;
jb.setText("Start");
// l.setflag(true);
}
}
}
然后是线程的代码:
package Game180710;
import java.util.Random;
import javax.swing.JLabel;
public class Lotterythread extends Thread {
private String str[]={"Lebron James","James Harden","Steven Curry","Kevin Duant","Ivring","Leonard"};
public JLabel label;
public volatile boolean flag=false;
public Lotterythread(JLabel label){
this.label=label;
//this.flag=flag;
// start();
}
//// public void setflag(boolean flag){
// this.flag=flag;
// }
public void run(){
while(true){
// System.out.println(flag);
if(flag)
{
int i=new Random().nextInt(str.length);
label.setText(str[i]);
System.out.println(label.getText());
try {
Thread.sleep(100); //用来控制休眠时间,抽奖系统的会转的很快很快
} catch (InterruptedException e) {
}
}
}
}
}
因为这个程序主要是为了学习线程,运行的结果只是一个简单的界面,就不展示结果了。
你会发现上面的代码中出现了很多注释,有些是调试用的,其实大部分之前出现过的错误。说实话代码不难,但是由于我一开始对线程的理解不够到位,导致了代码的思路其实很混乱,改了好久才改对,索性我就把注释留下当做一种提醒吧。
说一下我犯过的几个错误:
1.让一个线程的start()执行了多次。其实一个线程一个start()就好了,多了会报错
2.
volatile关键字的使用。如果没用这个关键字,main中的flag和线程中的flag可能无法实现同 步,导致无法正常变换按钮的内容;
3.OOP的理解还不算很到位,出现了一些低级错误。这个我在下一篇文章会继续分享我的看法。