Ⅰ 全面了解java媒体架构JMF
Java媒体架构(JMF)是一个令人激动的通用的API 它允许Java开发者用许多不同的方法处理媒体 本指南主要通过使用工作的例子提供一个JMF的一些主要的特征的概述 阅读完本指南后 你将会明白JMF体系结构中的主要播放功能 你同样能正确的使用JMF 使用现存的例子和可为更多特殊功能扩展的源代码
本指南包含着以下主题
· 下载和安装JMF
· 主要的JMF类以及它们在JMF体系结构中的应用
· 播放本地的媒体文件
· 为媒体的存取和操作制作以和图形用户界面(GUI)
· 通过网络传播媒体
· 通过网络接收媒体
几乎所有的媒体类型的操作和处理都可以通过JMF来实现 全面的讨论JMF所提供的所有特征已经超过了本指南的范围 我们将使用三个简单的媒体应用程序来学习此框架的构建模块 通过这个方法 本指南将为你未来学习和实施更多特殊的应用提供准备
我应该使用此指南吗?
本指南会带你学习使用JMF工作的基础 为完成这些 我们会创建三个的独立工作的例程序 每个例子都会建立前一个例子的基础上 显示JMF功能性的不同方面
在本指南中的例子假定你曾经使用过并且已经熟悉了Java程序语言 除了Java核竖衡颂心和JMF的类之外 我们会使用一些Java AWT和Swing类(用于创建GUI) 也会有一些Java网络类(用于在网络中传输媒体) 对GUI和网络类一些熟悉有助于你更快的明白观点和这里的例子 但并非是阅读本指南必须的
我们将学习的例程序如下
· 一个简单的音频播放器(JMF的HelloWorld应用) 这个字符界面的播放器通过在命令行中简单的输入媒拦吵体文件的名字就可以播放大多数的音频类型 此音频播放器的演示大体上显示了JMF的特有的类
· 一个图形界面的媒体播放器 我们将使用JMF内置的接口组件来建立图形界面 所以在此练习中必须有一些图形界面的编程经验 这个媒体阅览器演示使用了一些Java AWT和Swing类来为用户显示图形组件
· 一个媒体广播应用 此应用程序允许一个本地媒体文件通过网络传播 此程序能灵活的使媒体只传输到指定的网络节点 或者传输到一个子网余郑络中的所有节点 此演示使用了一些Java的网络APIs来在网络中传输媒体
作为第三个练习的一部分 我们将修改图形界面的播放器 让其能接收并且播放媒体
跳至 页观看Resources 文章 指南 和其他参考书目的列表 这会帮助你学习到更到关于此指南包括的主题
安装需求
要运行此指南中的例程序 你需要如下的工具和组件
·Java 平台 标准版 编译和运行演示程序
·Java媒体框架 版本 a或者更高
· 一块已经安装并且配置号的适当的声卡
· 一台或者多台测试机器
· 演示的源代码文件在mediaplayer jar中
最后的一个演示应用显示了JMF在网络中的应用 如果需要 此演示能运行在一个独立的机器上 使用此机器即是传输方也是接收方 可是要观察到在网络中使用JMF的所有功能 你仍然需要至少两台联网的机器
在 页中的Resources可下载Java 平台 完整的源代码文件 以及其他一些完成本指南所需要的工具
下载安装文件
将JMF安装到你的计算机中的第一步是在JMF的主页中下载安装文件 它同样包括了JMF源代码和API文档的链接 页的Resources中有下载JMF的链接
目前 JMF有Windows Solaris Linux等版本 以及可运行在任何装有虚拟机的计算机上一个纯Java版本 为了增加性能 你需要下载一个与你操作系统所适应的版本 任何在一个操作系统JMF版本下书写和编译的代码都可以方便的移植到另外的操作系统上 例如 如果你下载了一个Solaris版本的JMF并且编译了一个类 这些类就可以在Linux上使用 不会有任何问题
作为选择 你可以选择下载纯Java版本 或者跨平台版本的JMF 这些版本没有使用操作系统特有的库文件 如果没有合适的JMF版本适合的操作系统 那么跨平台版本就是一个不错的选择
安装JMF
下载完JMF安装程序后 双击安装程序的图标
大部分安装程序都会有个选项 安装本地库到系统目录中;例如 Windows版本安装程序会有一个选项 Move DLLs to Windows/System directory 最好将此选项选中 因为它能确保这些操作系统的库文件能正确的安装
在安装的过程中 你还需要选择项目来更新系统的CLASSPATH和PATH变量 如果这些选项被关闭 那么在你编译和运行本指南的例程序的时候就需要在classpath中引入JMF的jar文件
第二节 一个简单的音频播放器
浏览
在本节中 我们将进行创建一个简单的音频播放器的第一个练习 本例将介绍Manager类和Player接口 中两个都是建立大多数基于JMF应用的重要部分
本例的功能目标是在字符界面下播放本地的音频文件 我们将学习此源代码 并了解每一行所做的任务 完成本节后 你将会有一个基于JMF的可播放包括MP WAV AU等多种音频文件的演示程序
在本练习后的源代码分类种可查询文件SimpleAudioPlayer java
引入必要的类
SimpleAudioPlayer类中包括了一些调用 在其前几行中需要引入所有必要的类
import dia *;import java io File;import java io IOException;import URL;import MalformedURLException;
The dia包是由JMF定义的多个包之一 dia是一个核心包 包括了定义Manager类和Player接口等 本节中 我们主要学习Manager类和Player接口 其余的dia类放在后面的章节中
除了引入dia声明外 以上的代码片断引入了一些创建媒体播放器的输入的声明
Player接口
在下面的代码片断中 创建一个公共类SimpleAudioPlayer并举例定义一个Player变量
public class SimpleAudioPlayer {private Player audioPlayer = null;
术语Player听起来由点熟悉 因为它是建立在我们公用的音频或者视频播放器的基础上的 事实上 这个接口的例子就像是当作它们的真实的副本 Players揭示了一个实体上的媒体播放器(如立体音箱系统或者VCR)涉及到功能上的方法 例如 一个JMF媒体播放器可以开始和结束一个媒体流 在本节种 我们将使用Player的开始和结束功能
在一个文件上创建一个Player
使用JMF获得一个特定媒体文件的Player实例非常简单 Manager类在JMF中如同一个工厂制作许多的特殊接口类型 包括Player接口 因此 Manager类的责任就是创建Player实例 如下例
public SimpleAudioPlayer(URL url) throws IOException NoPlayerException CannotRealizeException{audioPlayer = Manager createRealizedPlayer(url);}public SimpleAudioPlayer(File file) throws IOException NoPlayerException CannotRealizeException{this(file toURL());
如果你看完本节的代码 你可以注意到Manager类包含了创建一个Player实例的其他方法 我们会研究其中的一些 如在后面的章节中的DataSource或者MediaLocator的实例化
Player的状态
JMF定义了大量的一个Player实例可能存在的不同状态 如下
· Prefetched
· Prefetching
· Realized
· Realizing
· Started
· Unrealized
使用这些状态
因为使用媒体常常是资源非常密集的 由JMF对象揭示的许多方法都是不闭塞的 允许一系列事件监听的状态改变的异步通知 例如 一个Player在它可以启动之前 必须经过Prefetched和Realized状态 由于这些状态的改变都需要一些时间来完成 JMF媒体应用可以分配一个线程来初始化创建Player实例 然后再继续其他的操作 当Player准备就绪的时候 它会通知应用程序其状态已经改变
在一个如同我们的这样简单的程序中 多功能性的类型并不是很重要 处于这个原因 Manager类也提供了一些创建Realized player的有用方法 调用一个createRealizedPlayer()方法来阻塞调用线程 直到player达到Realized状态 为了调用一个无阻塞的创建player的方法 我们在Manager类中使用了一个createPlayer()方法 下面的一行代码中创建了一个我们需要在例程序中使用的
Realized player audioPlayer = Manager createRealizedPlayer(url);
启动和停止Player
设定一个Player实例的启动或是停止就如同调用Player的一个简单的认证方法 如下所示
public void play() {audioPlayer start();}public void stop() {audioPlayer stop();audioPlayer close();}
调用SimpleAudioPlayer类中的play()方法来实现调用Player实例的start()方法 调用此方法后 你能听到本地的喇叭的声音文件 同样的 stop()方法使player停止并且关闭掉Player对象
对于读取和或者播放本地媒体文件来说 关闭Player实例释放所有资源是一个有用的方法 因为这是一个简单的例子 关闭Player是终止一个会话可接受的方法 但是在实际的应用中 你需要小心的确认在除掉Player之前必须要关闭掉 一但你已经关闭掉player 在再次播放一个媒体之前你必须要创建一个新的Player实例
lishixin/Article/program/Java/hx/201311/26628
Ⅱ 求 JAVA 异步观察者模式 的源代码(完整的),不要同步的,好的给加分
package TestObserver;
import java.util.Iterator;
import java.util.Vector;
/**
*
* @author Seastar
*/
interface Observed {
public void addObserver(Observer o);
public void removeObserver(Observer o);
public void update();
}
interface Observer {
public void takeAction();
}
class Invoker {
private Observer o;
Handler handler;
public Invoker(Observer o) {
new Handler();
this.o = o;
}
private class Handler extends Thread {
public Handler() {
handler = this;
}
@Override
public void run() {
o.takeAction();
}
}
public boolean TestSameObserver(Observer o) {
return o == this.o;
}
public void invoke() {
handler.start();
}
}
class ObservedObject implements Observed {
private Vector<Invoker> observerList = new Vector<Invoker>();
public void addObserver(Observer o) {
observerList.add(new Invoker(o));
}
public void removeObserver(Observer o) {
Iterator<Invoker> it = observerList.iterator();
while (it.hasNext()) {
Invoker i = it.next();
if (i.TestSameObserver(o)) {
observerList.remove(i);
break;
}
}
}
public void update() {
for (Invoker i : observerList) {
i.invoke();
}
}
}
class ObserverA implements Observer {
public void takeAction() {
System.out.println("I am Observer A ,state changed ,so i have to do something");
}
}
class ObserverB implements Observer {
public void takeAction() {
System.out.println("I am Observer B ,i was told to do something");
}
}
class ObserverC implements Observer {
public void takeAction() {
System.out.println("I am Observer C ,I just look ,and do nothing");
}
}
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
ObserverA a = new ObserverA();
ObserverB b = new ObserverB();
ObserverC c = new ObserverC();
ObservedObject oo = new ObservedObject();
oo.addObserver(a);
oo.addObserver(b);
oo.addObserver(c);
for (int i = 0; i < 5; ++i) {
oo.addObserver(new Observer() {
public void takeAction() {
System.out.println("我是山寨观察者"+",谁敢拦我");
}
});
}
//sometime oo changed ,so it calls update and informs all observer
oo.update();
}
}
观察者模式的精髓在于注册一个观察者观测可能随时变化的对象,对象变化时就会自动通知观察者,
这样在被观测对象影响范围广,可能引起多个类的行为改变时很好用,因为无需修改被观测对象的代码就可以增加被观测对象影响的类,这样的设计模式使得代码易于管理和维护,并且减少了出错几率
至于异步机制实际是个噱头,可以有观测对象来实现异步,也可以有观察者自身实现,这个程序实际是观测对象实现了异步机制,方法是在观察者类外包装了一层invoker类
Ⅲ java关于异步请求http接口
异步请求,那就是开启一条线程来发个http请求
等这条线程得到数据后,再通知主线程
android上的话,就有一个异步任务AnsyTask就是用来处理异步任务了
Ⅳ java中如何设计异步调用接口,用监听实现异步结果的通知
向对方注册本地的接收接口
像微信
~~~~~~~~
Ⅳ 如何用Java回调和线程实现异步调用
软件模块之间的调用关系可以分为两大类:即同步调用和异步调用。在同步调用中,一段代码(主调方)调用另一段代码(被调方),主调方必须等待这段代码执行完成返回结果后,才能继续往下执行,所以,同步调用是一种阻塞式调用,主调方代码一直阻塞等待直到被调方返回为止。同步调用相对比较直观,也是大部分编程语言直接支持的一种调用方式。但是,同步调用在处理比较耗时的情况下会严重影响程序性能,影响人机交互的瞬时反应。例如,某个程序需要访问数据库获取大量数据,然后根据这些数据进行一系列处理,将处理结果显示在程序主窗口。由于数据库访问和大量数据的处理都是耗时的工作,在这个工作完成之前,处理结果迟迟不能显示,用户点击鼠标也不会立即得到响应,让用户感到整个程序显得很沉重。面对这样一些需要比较长时间才能完成的应用场景,我们需要采用一种非阻塞式调用方式,即异步调用方式。在异步调用中,主调方调用被调方后,不等待对方返回结果就继续执行后续代码,被调方执行完毕后,通过某种手段通知调用方:结果已经出来,请酌情处理。我们可以对上面的例子改用异步调用将问题轻松化解:把整个耗时的工作放进一个单独的线程,由主调方启动此线程后继续执行后续代码,线程在背后悄悄地处理费时的工作,当工作完成,采用回调的方式通知主调方工作完成,主调方将结果显示在主窗口。经过这样的处理,主界面继续进行自己的工作而不必死等,就不会造成界面响应迟钝。
在实现异步调用机制时,除了线程之外,还要用到回调。回调是一种双向调用,也就是,被调方在被调用时也会调用主调方的代码。在异步调用中,被调方需要在工作完成时通知主调方,即调用主调方的接口,这一机制通过回调实现。回调和异步调用的关系非常紧密,回调是异步调用的基础[1]。
本文理论联系实际,首先阐述如何使用Java实现回调机制,然后进一步阐述使用Java回调和线程实现异步调用,最后,阐述在异步调用中如何处理超时问题。
1 Java回调机制的实现方法
实现Java回调,需要做如下三件事情:
(1)定义一个回调接口CallbackInterface
接口中声明回调方法handle,如图1所示,回调方法就是一个普通的方法,接收一个消息字符串或者一个封装了数据的事件。
(2)定义一个类实现回调接口
这个类其实就是消息接收者和处理者,也就是调用方,回调方法是消息发生时实际处理消息的方法,此处简化为一条打印语句。
(3)定义消息通知者
消息通知者也就是被调用方必须具备两种能力,第一,它必须知道谁是消息接收者,第二,当消息发生时,它能够回调这些接收者的回调方法。为了获得这两种能力,消息通知者首先必须提供一个注册方法register, 通过注册的方式来注册多个对此消息或事件感兴趣的对象。然后提供一个消息通知方法notifyMessage,在这个方法中调用所有消息接收者的回调方法。具体代码如图3所示。
比如用一个可变数组List用于保存消息接收者,注册的过程实际上是将消息接收者添加到这个数组,以备在需要通知消息的时候调用这些消息接收者的回调方法。
使用Java回调和线程实现异步调用
线程是一个独立的执行流,其本质是程序中一段并发执行的代码。在异步调用机制中引入线程,在线程中完成耗时的工作,其目的是让调用方的主线程继续执行后续代码而不需要等待被调方的结果返回。由于不需要等待,这样我们就等于同时做了两件事情,而这两件事情分别是在不同的执行流中执行,主调者在当前的主线程中执行,被调者在另外一个线程中执行,因此提高了程序的效率,避免了界面的响应迟钝。当被调者执行完成后,仍然采用回调通知主调者。
例如LongTimeWorker是一个用于完成耗时工作的线程,同时又是消息通知者。其耗时工作在run方法中完成,另外提供一个注册方法register, 和一个消息通知方法notifyMessage,在run方法的最后,即耗时工作完成以后,调用notifyMessage将消息广播出去。
3 异步调用中超时问题的处理
异步调用通常都要加入超时机制,因为我们总是希望在一个指定的时间范围内返回一个结果,即使没有得到结果也该有个超时通知。这时我们需要使用“限时线程回调方式”,它在原有线程回调的基础上加上一个计时器Timer以计算消耗的时间,如果时间期限到了任务还没有执行完成即中断线程,并将超时消息广播出去。LongTimeWorker类需要修改部分的代码如图8和图9所示。
首先LongTimeWorker线程类增加了一个构造方法,其参数是超时时间timeout,构造方法的主要任务是创建一个定时器,每秒钟计时一次,若超时时间到则终止本线程,并广播超时消息。LongTimeWorker线程类的第二个改变发生在其run方法中,线程一启动立即开始计时,完成工作后停止计时,并广播消息。
4 结束语
异步调用是一种非阻塞式调用方式,用于在处理比较耗时的任务时保证程序性能不受到影响。实现异步调用的关键在于要解决三个技术难题,它们分别是程序阻塞问题、异步消息的传递问题和超时问题。本文介绍的方法采用并发线程、回调机制和计时器使上述问题得到了圆满解决。