多线程
一、
进程:
进程是程序的一次动态执行过程,经历从代码加载、代码执行到执行完毕的一个完整过程。一个应用程序就是一个进程。多进程操作系统能同时运行多个进程(程序),由于CPU具备分时机制,所以每个进程都能循环获得自己的CPU时间片。
线程:
每个Java程序都至少有一个线程——主线程。当一个Java程序启动时,JVM会创建主线程,并且在该线程中调用程序的main()方法。
1、单线程:
之前接触的都是单线程程序,单线程的特点是,被调用的方法执行完毕后当前方法才可能完成,前一个方法完成后才进行下一个方法。这是一种顺序调用。
2、多线程:
当程序同时用多个线程调用不同方法时,并不是像单线程一样的顺序调用,而是启动独立的线程之后立刻返回,各线程运行从run()方法开始,当run()结束后线程运行结束。
3、线程的优点——并行、省时。
单核CPU是通过暂停与切换实现多线程的。
进程与线程的区别:
(1)一个应用程序就是一个进程,而线程是一个进程内部的多个运行单位。
(2)多进程的内部数据和状态都是完全独立的,而多线程是共享一块内存空间和一组系统资源(在同一进程内),在程序内部可以相互调用。
(3)线程本身的数据通常只有寄存器数据,以及一个程序执行时使用的堆栈,所以线程的切换比进程切换的负担小。
二、
每个线程对象都继承了java.lang包中的Thread类,或implements了Runnable接口类。
线程的启动:start()方法;
线程的运行:run()方法。
java多线程的实现
1、继承Thread类实现线程。重写Thread类的run()方法
2、实现Runnable接口创建线程
Runnable接口只有一个run()方法没有start()方法,所以在使用Runnable接口的实现类创建线程时,启动线程要构造一个Thread对象,并调用它的start()方法来启动线程。
3、使用匿名内部类创建线程
在实例化Runnable方法时使用匿名内部类重写run()方法。然后再用Thread对象的start()方法启动线程。
如果run()方法要用到while(true){....}时,会发现CPU的占用率是100%。这时就要让线程隔一段时间暂停一下。在线程运行时,调用一个静态方法sleep(long time),可以让线程暂停time时间后再开始运行,暂停的时间以毫秒计。Thread.sleep(long time)只会让线程暂停(挂起),不是停止也不是退出。当线程在sleep时如果JVM或其他线程强行终止这个线程,sleep方法会抛出线程中断异常InterruptedException,所以需要处理。
三、
使用线程做一个小闹钟。
闹钟响起时弹出一个小窗口,可以选择停止不再闹响,或者再睡一会儿再闹响。
如有不足欢迎指正! <script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
一、
进程:
进程是程序的一次动态执行过程,经历从代码加载、代码执行到执行完毕的一个完整过程。一个应用程序就是一个进程。多进程操作系统能同时运行多个进程(程序),由于CPU具备分时机制,所以每个进程都能循环获得自己的CPU时间片。
线程:
每个Java程序都至少有一个线程——主线程。当一个Java程序启动时,JVM会创建主线程,并且在该线程中调用程序的main()方法。
1、单线程:
之前接触的都是单线程程序,单线程的特点是,被调用的方法执行完毕后当前方法才可能完成,前一个方法完成后才进行下一个方法。这是一种顺序调用。
2、多线程:
当程序同时用多个线程调用不同方法时,并不是像单线程一样的顺序调用,而是启动独立的线程之后立刻返回,各线程运行从run()方法开始,当run()结束后线程运行结束。
3、线程的优点——并行、省时。
单核CPU是通过暂停与切换实现多线程的。
进程与线程的区别:
(1)一个应用程序就是一个进程,而线程是一个进程内部的多个运行单位。
(2)多进程的内部数据和状态都是完全独立的,而多线程是共享一块内存空间和一组系统资源(在同一进程内),在程序内部可以相互调用。
(3)线程本身的数据通常只有寄存器数据,以及一个程序执行时使用的堆栈,所以线程的切换比进程切换的负担小。
二、
每个线程对象都继承了java.lang包中的Thread类,或implements了Runnable接口类。
线程的启动:start()方法;
线程的运行:run()方法。
java多线程的实现
1、继承Thread类实现线程。重写Thread类的run()方法
- public class ThreadDemo extends Thread{
- //要统计的磁盘路径
- private String path;
- //构造方法
- public ThreadDemo(String path){
- this.path = path;
- }
- //主方法
- public static void main(String[] args){
- //得到根目录
- File[] root = File.listRoots();
- for(int i=0;i<root.length;i++){
- //创建线程对象
- ThreadDemo td = new ThreadDemo(root[i].getAbsolutePath());
- td.start();
- }
- }
- //重写run方法
- public void run(){
- long start = System.currentTimeMillis();
- System.out.println("开始时间:"+start);
- int num = countFile(path);
- long end = System.currentTimeMillis();
- System.out.println("结束时间:"+end);
- System.out.println(path+"统计共有"+num+"个文件!");
- }
- //统计文件数目的方法
- public int countFile(String path){
- int count = 0;
- File file = new File(path);
- //得到该目录下的所有文件
- File[] subFile = file.listFiles();
- //如果该目录为空或
- if(null==subFile||subFile.length==0){
- return count;
- }
- for(int i=0;i<subFile.length;i++){
- if(subFile[i].isDirectory()){
- count+=countFile(subFile[i].getAbsolutePath());
- }else if(subFile[i].isFile()){
- count++;
- }
- }
- return count;
- }
- }
2、实现Runnable接口创建线程
Runnable接口只有一个run()方法没有start()方法,所以在使用Runnable接口的实现类创建线程时,启动线程要构造一个Thread对象,并调用它的start()方法来启动线程。
3、使用匿名内部类创建线程
在实例化Runnable方法时使用匿名内部类重写run()方法。然后再用Thread对象的start()方法启动线程。
如果run()方法要用到while(true){....}时,会发现CPU的占用率是100%。这时就要让线程隔一段时间暂停一下。在线程运行时,调用一个静态方法sleep(long time),可以让线程暂停time时间后再开始运行,暂停的时间以毫秒计。Thread.sleep(long time)只会让线程暂停(挂起),不是停止也不是退出。当线程在sleep时如果JVM或其他线程强行终止这个线程,sleep方法会抛出线程中断异常InterruptedException,所以需要处理。
三、
使用线程做一个小闹钟。
- /**
- * 闹钟界面类——每天都会定时响起
- * @author 客
- *
- */
- public class ClockTest extends JFrame implements Runnable{
- //设置时间格式
- private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- //设置当前时间为now
- private String now = "";
- //设置闹醒时间为alarm
- private String alarm = "";
- //第二个文本框为tf2
- TextField tf2;
- /**
- * 主方法
- * @param args
- */
- public static void main(String[] args){
- ClockTest clock = new ClockTest();
- clock.init();
- //创建线程
- Thread thread = new Thread(clock);
- thread.start();
- }
- /**
- * 窗口初始化
- */
- public void init(){
- this.setTitle("闹钟设置");
- this.setSize(350,200);
- this.setLocationRelativeTo(null);
- this.setDefaultCloseOperation(3);
- JPanel south = new JPanel();
- south.setPreferredSize(new Dimension(350,90));
- south.setBackground(Color.LIGHT_GRAY);
- this.add(south,BorderLayout.SOUTH);
- //创建标签,文本框,按钮
- JLabel label1 = new JLabel("闹醒时间:");
- final TextField tf1 = new TextField("07:00");
- JLabel label2 = new JLabel("间隔时间:");
- tf2 = new TextField("5");
- JLabel label3 = new JLabel("分钟");
- JButton btn = new JButton("确定");
- south.add(label1);
- south.add(tf1);
- south.add(label2);
- south.add(tf2);
- south.add(label3);
- south.add(btn);
- //匿名内部类监听button
- ActionListener action = new ActionListener(){
- public void actionPerformed(ActionEvent e) {
- //按钮被点击时,获取tf1中的闹醒时间内容,加入秒钟赋值给字符串alarm(全局变量)
- alarm = tf1.getText()+":00";
- }
- };
- //给按钮添加动作监听器
- btn.addActionListener(action);
- //设置窗体可见
- this.setVisible(true);
- }
- /**
- * 重写run方法,线程运行
- */
- public void run(){
- while(true){//连续不断
- //创建一个Date对象,
- Date date = new Date();
- //以sdf的形式得到时间
- now = sdf.format(date);
- repaint();
- //截取现在时间的后半部分:即时分秒,
- String now_time = now.substring(11, 19);
- //输出tf1中记录的时间-时分秒,和现在的时分秒
- System.out.println("------>now_time"+now_time+" ----->alarm"+alarm);
- //判断是否相等
- if(alarm.equals(now_time)){
- System.out.println("闹响!");
- //创建一个Timer对象
- Timer timer = new Timer();
- //得到tf2中的内容,将其转换成整型
- int i = Integer.parseInt(tf2.getText());
- //创建一个TimerTask的继承子类,调用重写了的run方法
- MyTimerTask task = new MyTimerTask();
- //调用Timer类中的schedule方法,从相等的时刻开始闹响,每次间隔时间为i分钟
- timer.schedule(task, 0, i*60*1000);
- }
- try {//线程休息1秒钟
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- /**
- * 重绘方法
- */
- public void paint(Graphics g){
- super.paint(g);
- //绘制当前时间
- g.drawString(now, 100, 80);
- }
- }
闹钟响起时弹出一个小窗口,可以选择停止不再闹响,或者再睡一会儿再闹响。
- /**
- * 闹钟响起时的类
- * @author 客
- *
- */
- public class MyTimerTask extends TimerTask{
- AudioClip mid ;
- /**
- * 重写TimerTask的run方法
- */
- public void run() {
- final JFrame jf = new JFrame("闹钟");
- jf.setSize(200, 80);
- jf.setLocationRelativeTo(null);
- jf.setDefaultCloseOperation(2);
- FlowLayout flow = new FlowLayout();
- jf.setLayout(flow);
- //创建两个按钮
- JButton btn_stop = new JButton(" 停 止 ");
- JButton btn_sleep = new JButton("再睡会儿");
- jf.add(btn_stop);
- jf.add(btn_sleep);
- btn_stop.setActionCommand("stop");
- btn_sleep.setActionCommand("sleep");
- //播放音乐
- String path = "F:\\001.MID";
- File f = new File(path);
- try {
- @SuppressWarnings("deprecation")
- URL url = f.toURL();
- mid = java.applet.Applet.newAudioClip(url);// this.getClass().getResource(s));
- mid.play();
- } catch (MalformedURLException e1) {
- e1.printStackTrace();
- }
- //匿名内部类给两个按钮添加监听
- ActionListener a_l = new ActionListener(){
- public void actionPerformed(ActionEvent e) {
- String command = e.getActionCommand();
- //如果选择停止,那么终止程序,如果选择睡觉,那么关闭当前窗口,等待下次闹钟
- if("stop".equals(command)){
- System.out.println("选择停止");
- //终止整个程序
- System.exit(0);
- }
- if("sleep".equals(command)){
- System.out.println("选择睡觉");
- //停止音乐
- mid.stop();
- //关闭当前小窗口
- jf.dispose(); }
- }
- };
- btn_stop.addActionListener(a_l);
- btn_sleep.addActionListener(a_l);
- //设置窗体可见
- jf.setVisible(true);
- }
- }
如有不足欢迎指正! <script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>