并发编程入门

简介: 并发编程一直是一个令人困惑的问题,主要的原因在于:使用并发时需要解决的问题会有很多;另外实现并发的方式不止一种,实现方式的选择也是一大问题。谈到并发,首先稍微介绍下什么是并发,相信很多人都已经对这个概念比较熟悉,并发编程是相对顺序编程的一种新的模式。

并发编程一直是一个令人困惑的问题,主要的原因在于:使用并发时需要解决的问题会有很多;另外实现并发的方式不止一种,实现方式的选择也是一大问题。

谈到并发,首先稍微介绍下什么是并发,相信很多人都已经对这个概念比较熟悉,并发编程是相对顺序编程的一种新的模式。它可以一定程度的提高程序的执行速度。主要针对程序的阻塞性,因为程序的阻塞使得程序运行效率降低,而并发在一定程度上解决了程序的阻塞性带来的运行效率问题。所以也可以说,从性能的角度看,如果没有任务会阻塞,那么单处理器上的并发就没有了意义。

看起来并发也没有多大的作用噢!平常的编程工作并没有遇到很多的阻塞问题,或者涉及到并发问题。就拿Java语言来说。其实不然,Servlet对于熟悉Java的人来说再熟悉不过,而这个作为Web系统最基础的一个类天生就具有多线程性,而对并发的熟悉能使得我们充分利用这些处理器。

并发编程使得我们可以将程序划分为多个分离的、独立运行的任务,通过多线程机制,这些独立任务中的每一个都将由执行线程来驱动。一个线程就是在进程中的一个单一的顺序控制流,因此,单个进程可以拥有多个并发执行的任务,但程序使得每个任务都好像有其自己的CPU一样。其底层机制是切分CPU时间片,这些通常不需要考虑。[p653]

了解了并发相关的一些概念,接下来学习学习Java中的并发编程。

Java中Runnable代表一个任务,要实现线程行为,需要显式地将这个任务附着到线程(Thread)上,

public class BasicThreads{
    public static void main (String args[]){
        Thread t = new Thread(new LiftOff());   //LiftOff是一个任务
        t.start();
    }
}

从任务中产生返回值

Runnable是执行工作的独立任务,他不返回任何值。如果希望在任务完成时能够返回一个值,那么可以实现Callable接口而不是Runnable接口。
如何使用Callable呢?
首先Callable是一种具有类型参数的泛型,它的类型参数表示的是从方法call()中返回的值;并且必须使用ExecutorService.submit()方法调用它,示例:

public class CallableDemo {
    public static void main(String args[]){
        ExecutorService exec = Executors.newCachedThreadPool();
        ArrayList<Future<String>> results = new ArrayList<Future<String>>();
        for (int i = 0; i < 10; i++) {
            results.add(exec.submit(new TaskwithResult(i)));
        }
        for(Future<String> fs : results){
            try {
                System.out.println(fs.get());
            }catch(Exception e){
                System.out.println(e);
            }finally {
                exec.shutdown();
            }
        }
    }
}

class TaskwithResult implements Callable<String>{
    private int id ;
    public TaskwithResult(int id){
        this.id = id ;
    }
    public String call(){
        return "result of TaskWithResult " + id ;
    }
}

submit()方法会产生Future对象,它用Callable返回结果的特定类型进行了参数化,可以用isDone()方法来查询Future是否已经完成。[p659]

优先级

线程的优先级,优先级较低的只是执行的频率比较低,并不是优先级低的将不会在优先级高的线程前执行(即,优先级不会导致死锁)。
在绝大多数时间,线程的优先级都应该以默认优先级运行,试图操作线程优先级通常是一种错误。

读取线程优先级

getPriority();

修改优先级

setPriority();

让步

yield();

给线程调度机制一个暗示:工作已经差不多了,可以让别的线程使用CPU了。

但是这个暗示没有任何机制保证它会被采纳。当调用这个方法时,只是在建议具有相同优先级的其他线程可以运行。

相关文章
|
2月前
|
安全 数据库连接 API
C#一分钟浅谈:多线程编程入门
在现代软件开发中,多线程编程对于提升程序响应性和执行效率至关重要。本文从基础概念入手,详细探讨了C#中的多线程技术,包括线程创建、管理及常见问题的解决策略,如线程安全、死锁和资源泄露等,并通过具体示例帮助读者理解和应用这些技巧,适合初学者快速掌握C#多线程编程。
82 0
|
6月前
|
安全 Java 调度
C++从入门到精通:3.3多线程编程
C++从入门到精通:3.3多线程编程
|
存储 算法 C++
[笔记]C++并发编程实战 《二》线程管理(二)
[笔记]C++并发编程实战 《二》线程管理(二)
|
存储 缓存 安全
[笔记]C++并发编程实战 《二》线程管理(一)
[笔记]C++并发编程实战 《二》线程管理
|
存储 缓存 算法
并发编程基础
并发编程基础
|
消息中间件 安全 算法
并发编程面试题2
并发编程面试题2
694 0
|
缓存 安全
并发编程学习一
并发编程学习一
77 0
|
缓存 安全 Java
并发编程面试题3
并发编程面试题3
65 0
|
存储 缓存 安全
并发编程面试题4
并发编程面试题4
88 0