欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

并发与多线程,

来源: javaer 分享于  点击 13063 次 点评:278

并发与多线程,


并发与多线程

基本概念

并发与并行

进程与线程

线程

创建线程

Thread

Runnable

多个 Thread 实例共用一个 Runnable,这些线程的 run 方法相同,可以共享相同的数据

但是存在线程同步问题

public class RunnableTest implements Runnable
{
    private int ticket = 10;
    public void run()
    {
        while (true)
        {
            if (ticket > 0)
            {
                System.out.println(Thread.currentThread().getName() + "售出" + ticket + "号票");
                ticket--;
            }
            else System.exit(0);
        }
    }
    public static void main(String[] args)
    {
        RunnableTest rt = new RunnableTest();
        Thread t1 = new Thread(rt, "1号窗口");
        Thread t2 = new Thread(rt, "2号窗口");
        t1.start();
        t2.start();
    }
}

print

1号窗口售出10号票
1号窗口售出9号票
1号窗口售出8号票
1号窗口售出7号票
2号窗口售出7号票
2号窗口售出5号票
1号窗口售出6号票
2号窗口售出4号票
1号窗口售出3号票
2号窗口售出2号票
1号窗口售出1号票

匿名类

匿名类可以方便的访问方法的局部变量,但是必须声明为 final,因为匿名类和普通局部变量生命周期不一致

jdk7 中已不再需要显示声明为 final,实际上被虚拟机自动隐式声明了

public static void main(String[] args)
{
    new Thread( )
    {
        public void run( )
        {
            //内容
        }
    }.start( );
    new Thread(new Runnable( )
    {
        public void run( )
        {
            //内容
        }
	}).start( );
}

Callable

线程方法

线程状态

线程同步

保证程序原子性、可见性、有序性的过程

阻塞同步

基于加锁争用的悲观并发策略

synchronized

ReentrantLock

非阻塞同步

非阻塞同步是一种基于冲突检测和数据更新的乐观并发策略

actomic 类

无同步方案

如果一个方法不涉及共享数据,那么他天生就是线程安全的

可重入代码

可以在代码执行的任何时刻中断它,转而去执行另外一段代码,在控制权返回之后,原来的程序不会出现任何的错误

线程本地存储

死锁

死锁条件

Java死锁示例

public static void main(String[] args)
{
    Object o1 = new Object( );
    Object o2 = new Object( );

    Thread t1 = new Thread( )
    {
        public void run( )
        {
            synchronized (o1)//占有 o1
            {
                System.out.println("t1 已占有 O1");
                try
                {
                    Thread.sleep(1000);//停顿1000毫秒,另一个线程有足够的时间占有 o1
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace( );
                }
                System.out.println("t1 试图占有 o2");
                System.out.println("t1 等待中");
                synchronized (o2)
                {
                    System.out.println("t1 已占有 O2");
                }
            }
        }
    };
    Thread t2 = new Thread( )
    {
        public void run( )
        {
            synchronized (o2)  //占有 o2
            {
                System.out.println("t2 已占有 o2");
                try
                {
                    Thread.sleep(1000);//停顿1000毫秒,另一个线程有足够的时间占有 o2
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace( );
                }
                System.out.println("t2 试图占有 o1");
                System.out.println("t2 等待中");
                synchronized (o1)
                {
                    System.out.println("t2 已占有 O1");
                }
            }
        }
    };
    t1.start( );
    t2.start( );
}

print

t1 已占有 O1
t2 已占有 o2
t1 试图占有 o2
t1 等待中
t2 试图占有 o1
t2 等待中

线程通信

public class ProducerAndConsumer
{
    public static void main(String[] args)
    {
        Goods goods = new Goods();
        Thread producer = new Thread()//生产者线程
        {
            public void run()
            {
                while (true) goods.put();
            }
        };
        Thread consumer = new Thread()//消费者线程
        {
            public void run()
            {
                while (true) goods.take();
            }
        };
        consumer.start();
        producer.start();
    }
}
class Goods//商品类
{
    int num = 0;//商品数目
    int space = 10;//空位总数
    public synchronized void put()
    {
        if (num < space)//有空位可放,可以生产
        {
            num++;
            System.out.println("放入一个商品,现有" + num + "个商品," + (space - num) + "个空位");
            notify();//唤醒等待该锁的线程
        }
        else//无空位可放,等待空位
        {
            try
            {
                System.out.println("没有空位可放,等待拿出");
                wait();//进入该锁对象的等待池
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
    public synchronized void take()
    {
        if (num > 0)//有商品可拿
        {
            num--;
            System.out.println("拿出一个商品,现有" + num + "个商品," + (space - num) + "个空位");
            notify();//唤醒等待该锁的线程
        }
        else///等待生产产品
        {
            try
            {
                System.out.println("没有商品可拿,等待放入");
                wait();//进入该锁对象的等待池
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
}

print

没有商品可拿,等待放入
放入一个商品,现有1个商品,9个空位
放入一个商品,现有2个商品,8个空位
拿出一个商品,现有1个商品,9个空位
放入一个商品,现有2个商品,8个空位
放入一个商品,现有3个商品,7个空位
放入一个商品,现有4个商品,6个空位
拿出一个商品,现有3个商品,7个空位
放入一个商品,现有4个商品,6个空位
···

线程池

线程的启动和结束都是比较消耗时间和占用资源的,如果在系统中用到了很多的线程,大量的启动和结束动作会严重影响性能

线程池很像生产者消费者模式,消费的对象是一个一个的能够运行的任务

线程安全类

相关文章

    暂无相关文章
相关栏目:

用户点评