一个简单的线程例子

本文介绍了一个简单的Java多线程程序示例,演示了如何通过线程间通信来控制线程执行流程,并讨论了同步方法的概念及其实现细节。此外,还通过一个死锁示例展示了多线程编程中可能出现的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SimpleThreads程序有两个线程组成,第一个是主线程,它从创建了一个线程并等待它执行完成。如果MessageLoop线程执行了太长时间,主线程将会将其中断。
MessageLoop现场将会打印一系列的信息。如果中断在它打印完所有信息前发生,它将会打印一个特定的消息并退出。
java 代码

    public class SimpleThreads {  

        // Display a message, preceded by  
        // the name of the current thread  
        static void threadMessage(String message) {  
            String threadName =  
                Thread.currentThread().getName();  
            System.out.format("%s: %s%n",  
                              threadName,  
                              message);  
        }  

        private static class MessageLoop  
            implements Runnable {  
            public void run() {  
                String importantInfo[] = {  
                    "Mares eat oats",  
                    "Does eat oats",  
                    "Little lambs eat ivy",  
                    "A kid will eat ivy too"  
                };  
                try {  
                    for (int i = 0;  
                         i < importantInfo.length;  
                         i++) {  
                        // Pause for 4 seconds  
                        Thread.sleep(4000);  
                        // Print a message  
                        threadMessage(importantInfo[i]);  
                    }  
                } catch (InterruptedException e) {  
                    threadMessage("I wasn't done!");  
                }  
            }  
        }  

        public static void main(String args[])  
            throws InterruptedException {  

            // Delay, in milliseconds before  
            // we interrupt MessageLoop  
            // thread (default one hour).  
            long patience = 1000 * 60 * 60;  

            // If command line argument  
            // present, gives patience  
            // in seconds.  
            if (args.length > 0) {  
                try {  
                    patience = Long.parseLong(args[0]) * 1000;  
                } catch (NumberFormatException e) {  
                    System.err.println("Argument must be an integer.");  
                    System.exit(1);  
                }  
            }  

            threadMessage("Starting MessageLoop thread");  
            long startTime = System.currentTimeMillis();  
            Thread t = new Thread(new MessageLoop());  
            t.start();  

            threadMessage("Waiting for MessageLoop thread to finish");  
            // loop until MessageLoop  
            // thread exits  
            while (t.isAlive()) {  
                threadMessage("Still waiting...");  
                // Wait maximum of 1 second  
                // for MessageLoop thread  
                // to finish.  
                t.join(1000);  
                if (((System.currentTimeMillis() - startTime) > patience)  
                      && t.isAlive()) {  
                    threadMessage("Tired of waiting!");  
                    t.interrupt();  
                    // Shouldn't be long now  
                    // -- wait indefinitely  
                    t.join();  
                }  
            }  
            threadMessage("Finally!");  
        }  
    }  

Java编程语言提供两种同步方式:同步方法和同步语句。
同步方法:
要让一个方法成为同步方法,只需要在方法声明中加上synchronized关键字:

    public class SynchronizedCounter {  
        private int c = 0;  

        public synchronized void increment() {  
            c++;  
        }  

        public synchronized void decrement() {  
            c--;  
        }  

        public synchronized int value() {  
            return c;  
        }  
    }  

如果count是SynchronizedCounter类的实例,那么让这些方法成为同步方法有两个作用:
首先,相同对象上的同步方法的两次调用,它们要交替执行是不可能的。 当一个线程正在执行对象的同步方法时,所有其他调用该对象同步方法的线程会被阻塞(挂起执行),直到第一个线程处理完该对象。

其次,当一个同步方法退出时,它会自动跟该对象同步方法的任意后续调用建立起一种happens-before关系。这确保对象状态的改变对所有线程是可见的。

注意构造方法不能是同步的——构造方法加synchronized关键字会报语法错误。同步的构造方法没有意义,因为当这个对象被创建的时候,只有创建对象的线程能访问它。

警告:当创建的对象会被多个线程共享时必须非常小心,对象的引用不要过早“暴露”出去。比如,假设你要维护一个叫instances的List,它包含类的每一个实例对象。你可能会尝试在构造方法中加这样一行:

    instances.add(this);  

死锁
死锁描述了这样一种情景,两个或多个线程永久阻塞,互相等待对方释放资源。下面是一个例子。

Alphone和Gaston是朋友,都很讲究礼节。礼节有一个严格的规矩,当你向一个朋友鞠躬时,你必须保持鞠躬的姿势,直到你的朋友有机会回鞠给你。不幸的是,这个规矩没有算上两个朋友相互同时鞠躬的可能。

下面的应用例子,DeadLock,模拟了这个可能性。

static class Friend {  
        private final String name;  
        public Friend(String name) {  
            this.name = name;  
        }  
        public String getName() {  
            return this.name;  
        }  
        public synchronized void bow(Friend bower) {  
            System.out.format("%s: %s"  
                + "  has bowed to me!%n",  
                this.name, bower.getName());  
            bower.bowBack(this);  
        }  
        public synchronized void bowBack(Friend bower) {  
            System.out.format("%s: %s"  
                + " has bowed back to me!%n",  
                this.name, bower.getName());  
        }  
    }  

    public static void main(String[] args) {  
        final Friend alphonse =  
            new Friend("Alphonse");  
        final Friend gaston =  
            new Friend("Gaston");  
        new Thread(new Runnable() {  
            public void run() { alphonse.bow(gaston); }  
        }).start();  
        new Thread(new Runnable() {  
            public void run() { gaston.bow(alphonse); }  
        }).start();  
    }  
}  

http://www.iteye.com/magazines/131-Java-Concurrency 原文链接
多线程单例实现:http://blog.youkuaiyun.com/shiyanming1223/article/details/6933420

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值