单线程和多线程

关于它们的区别,zhihu上有一个回答,我认为十分不错,如下:

. 单进程单线程:一个人在一个桌子上吃菜。
. 单进程多线程:多个人在同一个桌子上一起吃菜。
. 多进程单线程:多个人每个人在自己的桌子上吃菜。

多线程的问题是多个人同时吃一道菜的时候容易发生争抢.例如两个人同时夹一个菜,一个人刚伸出筷子,结果伸到的时候已经被夹走菜了。此时就必须等一个人夹一口之后,在还给另外一个人夹菜,也就是说资源共享就会发生冲突争抢。

例子:
多线程:
浏览器浏览一个页面,里面有很多图片,多线程,每个线程下载一副图片,他们相当于一个桌子上不同的菜。

多进程:
浏览器开了多个标签浏览不同网站,多进程,因为他们相当于“不同的桌子” 

原文链接:http://www.zhihu.com/question/19901763

如何创建线程

方式1:

MultiThreading.java

public class MultiThreading {
    public static void main(String[] args) {
        NewThread thread1 = new NewThread();
        NewThread thread2 = new NewThread();

        thread1.start();
        thread2.start();
    }
}

class NewThread extends Thread {                                //继承Thread类
    private static int num = 0;
    public NewThread() {
        super("THread:" + ++num);                               //通过Thraed的构造方法,初始化线程的名字
                                                                //public Thread(String name)
    }

    //重写Thread的run()方法,然后通过Thread的start()方法调用run()方法,实现多线程
    @Override
    public void run() {
        while (true) {
            System.out.println(super.getName() + " is running~");//getName():获取线程的名字
        }
    }
}

方式2:实现Runnable接口

MultiThreading2.java

public class MultiThreading2 {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new NewThread("线程1"));
        Thread thread2 = new Thread(new NewThread("线程2"));

        thread1.start();
        thread2.start();
    }
}

class NewThread implements Runnable {
    private String threadName = null;

    public NewThread(String threadName) {
        this.threadName = threadName;
    }   

    @Override
    public void run() {
        while (true) {
            System.out.println(this.threadName + " is running~");
        }
    }
}

看下Thread类的构造方法,   "public Thread(Runnable target)", 不难懂上面那个小例子.

synchronized

我们考虑一个问题,如果一个桌子上有三个人(Person)在吃100个汉堡包(Hamburger), 当只有一个汉堡包的时候,其中的一个人判断还有一个汉堡包(hamburgerNum > 0), 所以执行了eatHamburger()操作, 而另一个人在这之前,也判断了还有一个汉堡包(hamburgerNum > 0), 想要执行eatHamburger()操作的时候, 那个汉堡包已经被别人吃了, 那么这个时候 (hamburgerNum--) 汉堡包的数量不就成了负数了吗? 这明显是不行的.

也就是说, "判断和吃"这个两个操作, 需要一个人一起执行成功后, 才能让另一个人执行. 所以我们需要把它们 "绑在一起", 也就是"锁"起来.这里就不要用到 "syncronized"(同步)这个修饰符了

Test.java

public class Test {
    public static void main(String[] args) {
        Hamburger h = new Hamburger(100);
        Person p1 = new Person(h);
        Person p2 = new Person(h);
        Person p3 = new Person(h);

        p1.start();
        p2.start();
        p3.start();
    }
}

class Person extends Thread {                       //继承Thread类,重写run()方法,通过调用Thread的start()方法,创建多个线程
    private int count = 0;                          //记录这个人吃了多少个汉堡包
    private String name = "小明";
    private static int num = 0;                     //这里需要使用static修饰
    private Hamburger hamburger = null;

    public Person(Hamburger hamburger) {
        this.hamburger = hamburger;
        this.name = this.name + (++num) + "号";
    }   

    @Override
    public void run() {
        while (true) {
            if (hamburger.eatHambergerNum()) {
                System.out.println(this.name + ": eat 1 Hamburger.");
                count++;
                try {
                    sleep((int)Math.random() * 100);                    //鄙人不明白为什么要这个句子?如果知道的请告知
                                                                        //或者,不需要这个句子?比人测试了,这个句子似乎没什么作用
                                                                        //线程不管"sleep"不"sleep",都不会永远分配给进程的霸占cpu吧
                } catch(InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                break;
            }
        }
        System.out.println(this.name + ": " + count);
    }
}

class Hamburger {
    private int hamburgerNum = 0;

    public Hamburger(int num) {
        this.hamburgerNum = num;
    }

    //注意这里使用了 "synchronized"修饰! "synchronized"也可以修饰语句块  用法: synchronized(对象) {}
    public synchronized boolean eatHambergerNum() {
        if (hamburgerNum > 0) {
            hamburgerNum--;
            return true;
        } else {
            return false;
        }
    }
}

参考:http://www.cnblogs.com/vamei/archive/2013/04/15/3000898.html

Java简明教程 12.多线程(multithreading)的更多相关文章

  1. Java基础教程:多线程基础(1)——基础操作

    Java:多线程基础(1) 实现多线程的两种方式 1.继承Thread类 public class myThread extends Thread { /** * 继承Thread类,重写RUN方法. ...

  2. Java基础教程:多线程基础(4)——Lock的使用

    Java基础教程:多线程基础(4)——Lock的使用 快速开始 Java 5中Lock对象的也能实现同步的效果,而且在使用上更加方便. 本节重点的2个知识点是:ReentrantLock类的使用和Re ...

  3. Java基础教程:多线程基础(2)——线程间的通信

    Java基础教程:多线程基础(2)——线程间的通信 使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时还会使程序员对各线程任务在处理的过程中进行有效的把控与监督. 线程间的通信 ...

  4. Java基础教程:多线程基础——线程池

    Java基础教程:多线程基础——线程池 线程池 在正常负载的情况瞎,通过为每一个请求创建一个新的线程来提供服务,从而实现更高的响应性. new Thread(runnable).start() 在生产 ...

  5. Java基础教程:多线程杂谈——双重检查锁与Volatile

    Java基础教程:多线程杂谈——双重检查锁与Volatile 双重检查锁 有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化.此时程序员可能会采用延迟初始化.但要正确实 ...

  6. Java基础教程:多线程基础(6)——信号量(Semaphore)

    Java基础教程:多线程基础(6)——信号量(Semaphore) 信号量 信号量(Semaphore)由一个值和一个指针组成,指针指向等待该信号量的进程.信号量的值表示相应资源的使用情况.信号量S≥ ...

  7. Java基础教程:多线程基础(5)——倒计时器(CountDownLatch)

    Java基础教程:多线程基础(5)——倒计时器(CountDownLatch) 引入倒计时器 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种 ...

  8. Java 简明教程

    本文为 Java 的快速简明教程,主要用于快速了解.学习和复习java的语法特点. // 单行注释 /* 多行注释 */ /** JavaDoc(Java文档)注释是这样的.可以用来描述类和类的属性. ...

  9. Java基础教程(12)--深入理解类

    一.方法的返回值   当我们在程序中调用方法时,虚拟机将会跳转到对应的方法中去执行.当以下几种情况发生时,虚拟机将会回到调用方法的语句并继续向下执行: 执行完方法中所有的语句: 遇到return语句: ...

随机推荐

  1. Charles拦截请求

    一.通过Charles抓包,可拦截请求并篡改交互信息 1.可篡改客户端向服务器发起的请求信息(服务器收到的是假消息) 2.可篡改服务器返回给客户端的响应结果(客户端看到的是假消息) 二.篡改用户请求 ...

  2. 题解 P1137 【旅行计划】

    传送门 很显然,每个点的答案是它所有前驱节点的答案加1,即f[i]=max(f[i],f[j]+1); 考虑空间复杂度用邻接表存图,在拓扑排序同时DP就好了 #include<iostream& ...

  3. SQL数据库查询出一张表中重复的数据,按某个字段来查找。

    例如表名为Course 需要查询出name重复的有那些??? 解答如下: 补充: 如:查询每个姓名出现大于2次,SQL如下 SELECT COUNT(NAME) as '出现次数',  NAME FR ...

  4. C/C++程序基础 (六)面向对象

    类的特性 抽象.封装.继承.多态.重载 class 和 struct 区别 C中struct仅仅可以包含数据成员,不可以有成员函数,属于复杂数据结构. C++ 中struct成员访问权限默认为publ ...

  5. dynamic routing between captual

    对于人脑 决策树形式 对于CNN 层级与层级间的传递 人在识别物体的时候会进行坐标框架的设置 CNN无法识别,只能通过大量训练 胶囊 :一个神经元集合,有一个活动的向量,来表示物体的各类信息,向量的长 ...

  6. 七、Linux 文件与目录管理

    Linux 文件与目录管理 我们知道Linux的目录结构为树状结构,最顶级的目录为根目录 /. 其他目录通过挂载可以将它们添加到树中,通过解除挂载可以移除它们. 在开始本教程前我们需要先知道什么是绝对 ...

  7. 自动化运维工具——ansible剧本playbook(三)

    一.Playbook--Ansible剧本 playbook是由一个或多个 "play"组成的列表 play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的ta ...

  8. Android Studio 安装与使用ADB wifi 无线调试

    首先,安装ADB WIFI File->Settings->Plugins 其次,用USB连接手机与电脑(并开启手机的调试模式) 任务栏若无提示,即可拔下USB线,开始无线调试 任务栏若是 ...

  9. JZOJ 5791. 【NOIP2008模拟】阶乘

    5791. [NOIP2008模拟]阶乘 (File IO): input:factorial.in output:factorial.out Time Limits: 1000 ms  Memory ...

  10. GoF23种设计模式之创建型模式之原型模式

    一.概述 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 二.适用性 1.当一个系统应该独立于它的产品创建.构成和表示的时候. 2.当要实例化的类是在运行时刻指定的时候,例如:通过动 ...