并发加对象锁_通用并发对象池

并发加对象锁

在本文中,我们将介绍如何在Java中创建对象池。 近年来,JVM的性能成倍增加,大多数类型的对象几乎都变得多余,从而提高了对象池的性能。 从本质上讲,对象的创建不再像以前那样昂贵。

但是,有些对象在创建时肯定会付出高昂的代价。 诸如线程,数据库连接对象之类的对象不是轻量级对象,并且创建起来稍微贵一些。 在任何应用程序中,我们都需要使用上述多种对象。 因此,如果有一种非常容易的方法可以轻松创建和维护该类型的对象池,那么可以动态使用和重用对象,而不必担心客户端代码对对象生命周期的影响,那就太好了。
在实际编写对象池的代码之前,让我们首先确定任何对象池必须回答的主要要求。

  • 池必须允许客户端使用对象(如果有)。
  • 一旦客户端将对象返回到池中,它就必须重用这些对象。
  • 如果需要,它必须能够创建更多对象以满足客户不断增长的需求。
  • 它必须提供适当的关闭机制,以便在关闭时不会发生内存泄漏。

毋庸置疑,以上几点将构成我们向客户公开的界面的基础。
因此,我们的接口声明如下:

package com.test.pool;/*** Represents a cached pool of objects.* * @author Swaranga** @param < T > the type of object to pool.*/
public interface Pool< T >
{/*** Returns an instance from the pool. * The call may be a blocking one or a non-blocking one * and that is determined by the internal implementation.* * If the call is a blocking call, * the call returns immediately with a valid object * if available, else the thread is made to wait * until an object becomes available.* In case of a blocking call, * it is advised that clients react * to {@link InterruptedException} which might be thrown* when the thread waits for an object to become available.* * If the call is a non-blocking one, * the call returns immediately irrespective of * whether an object is available or not.* If any object is available the call returns it * else the call returns < code >null< /code >.* * The validity of the objects are determined using the* {@link Validator} interface, such that * an object < code >o< /code > is valid if * < code > Validator.isValid(o) == true < /code >.* * @return T one of the pooled objects.*/T get();/*** Releases the object and puts it back to the pool.* * The mechanism of putting the object back to the pool is* generally asynchronous, * however future implementations might differ.* * @param t the object to return to the pool*/void release(T t);/*** Shuts down the pool. In essence this call will not * accept any more requests * and will release all resources.* Releasing resources are done * via the < code >invalidate()< /code >* method of the {@link Validator} interface.*/void shutdown();
}

上面的接口特意变得非常简单和通用,以支持任何类型的对象。 它提供了从池中获取对象或将对象返回池中的方法。 它还提供了一种关闭机制来处理对象。

现在,我们尝试创建上述接口的实现。 但是在此之前,必须注意,理想的release()方法将首先尝试检查客户端返回的对象是否仍然可重用,这一点很重要。 如果是,则它将返回到池,否则必须丢弃该对象。 我们希望Pool接口的每个实现都遵循此规则。 因此,在创建具体的实现之前,我们创建一个抽象的实现帽子,将这种限制强加给后续的实现。 我们的抽象实现将被称为Surprise,AbstractPool,其定义如下:

package com.test.pool;/*** Represents an abstract pool, that defines the procedure* of returning an object to the pool.* * @author Swaranga** @param < T > the type of pooled objects.*/
abstract class AbstractPool < T > implements Pool < T >
{/*** Returns the object to the pool. * The method first validates the object if it is* re-usable and then puts returns it to the pool.* * If the object validation fails, * some implementations* will try to create a new one * and put it into the pool; however * this behaviour is subject to change * from implementation to implementation* */@Overridepublic final void release(T t){if(isValid(t)){returnToPool(t);}else{handleInvalidReturn(t);}}protected abstract void handleInvalidReturn(T t);protected abstract void returnToPool(T t);protected abstract boolean isValid(T t);
}

在上面的类中,我们强制对象池必须先验证对象,然后再将其返回到池中。 为了自定义其池的行为,实现可以自由选择它们实现三种抽象方法的方式。 他们将决定使用自己的逻辑,如何检查对象是否对重用有效[validate()方法,如果客户端返回的对象无效[该方法,handleInvalidReturn()方法]和实际逻辑,该怎么办将有效对象返回到池中[returnToPool()方法)。

现在有了上面的类集,我们几乎可以进行具体的实现了。 但是要注意的是,由于上述类旨在支持通用对象池,因此上述类的通用实现将不知道如何验证对象[因为对象将是通用的:-)。 因此,我们需要其他可以帮助我们的东西。

我们实际上需要的是一种验证对象的通用方法,这样,具体的Pool实现就不必担心正在验证的对象的类型。 因此,我们引入了一个新的接口Validator,该接口定义了验证对象的方法。 我们对Validator接口的定义如下:

package com.test.pool;/*** Represents the functionality to * validate an object of the pool* and to subsequently perform cleanup activities.* * @author Swaranga** @param < T > the type of objects to validate and cleanup.*/public static interface Validator < T >{/*** Checks whether the object is valid.* * @param t the object to check.* * @return true * if the object is valid else false .*/public boolean isValid(T t);/*** Performs any cleanup activities * before discarding the object.* For example before discarding * database connection objects,* the pool will want to close the connections. * This is done via the * invalidate() method.* * @param t the object to cleanup*/public void invalidate(T t);}

上面的接口定义了检查对象是否有效的方法,以及使对象无效的方法。 当我们要丢弃对象并清除该实例使用的任何内存时,应使用invalidate方法。 注意,此接口本身没有什么意义,仅在对象池的上下文中使用时才有意义。 因此,我们在顶级Pool接口中定义此接口。 这类似于Java Collections库中的Map和Map.Entry接口。 因此,我们的Pool接口如下所示:

package com.test.pool;/*** Represents a cached pool of objects.* * @author Swaranga** @param < T > the type of object to pool.*/
public interface Pool< T >
{/*** Returns an instance from the pool. * The call may be a blocking one or a non-blocking one * and that is determined by the internal implementation.* * If the call is a blocking call, * the call returns immediately with a valid object * if available, else the thread is made to wait * until an object becomes available.* In case of a blocking call, * it is advised that clients react * to {@link InterruptedException} which might be thrown* when the thread waits for an object to become available.* * If the call is a non-blocking one, * the call returns immediately irrespective of * whether an object is available or not.* If any object is available the call returns it * else the call returns < code >null< /code >.* * The validity of the objects are determined using the* {@link Validator} interface, such that * an object < code >o< /code > is valid if * < code > Validator.isValid(o) == true < /code >.* * @return T one of the pooled objects.*/T get();/*** Releases the object and puts it back to the pool.* * The mechanism of putting the object back to the pool is* generally asynchronous, * however future implementations might differ.* * @param t the object to return to the pool*/void release(T t);/*** Shuts down the pool. In essence this call will not * accept any more requests * and will release all resources.* Releasing resources are done * via the < code >invalidate()< /code >* method of the {@link Validator} interface.*/void shutdown();/*** Represents the functionality to * validate an object of the pool* and to subsequently perform cleanup activities.* * @author Swaranga** @param < T > the type of objects to validate and cleanup.*/public static interface Validator < T >{/*** Checks whether the object is valid.* * @param t the object to check.* * @return true * if the object is valid else false .*/public boolean isValid(T t);/*** Performs any cleanup activities * before discarding the object.* For example before discarding * database connection objects,* the pool will want to close the connections. * This is done via the * invalidate() method.* * @param t the object to cleanup*/public void invalidate(T t);}
}

我们几乎准备好具体实施了。 但是在此之前,我们需要一种最终的武器,它实际上是对象池中最重要的武器。 这被称为“创建新对象的能力”。c我们的对象池将是通用的,它们必须具有如何创建新对象以填充其池的知识。 此功能也必须不依赖于对象池的类型,并且必须是创建新对象的常用方法。 完成此操作的方法将是一个称为ObjectFactory的接口,该接口仅定义一种方法,即“如何创建新对象”。 我们的ObjectFactory接口如下:

package com.test.pool;/*** Represents the mechanism to create * new objects to be used in an object pool.* * @author Swaranga** @param < T > the type of object to create. */
public interface ObjectFactory < T >
{/*** Returns a new instance of an object of type T.* * @return T an new instance of the object of type T*/public abstract T createNew();
}

最后,我们完成了我们的帮助程序类,现在我们将创建Pool接口的具体实现。 因为我们想要一个可以在并发应用程序中使用的池,所以我们将创建一个阻塞池,如果该池中没有可用的对象,它将阻塞客户端。 阻塞机制将无限期阻塞,直到对象可用为止。 这种实现方式引起了另一种方法,该方法将仅在给定的超时时间段内阻塞,如果在返回该对象的超时之前有任何对象可用,否则在超时之后而不是永远等待,则返回空对象。 此实现类似于Java Concurrency API的LinkedBlockingQueue实现,因此在实现实际的类之前,我们公开另一个实现BlockingPool,该实现类似于Java Concurrency API的BlockingQueue接口。

因此,Blockingpool接口声明如下:

package com.test.pool;import java.util.concurrent.TimeUnit;/*** Represents a pool of objects that makes the * requesting threads wait if no object is available.* * @author Swaranga** @param < T > the type of objects to pool.*/
public interface BlockingPool < T > extends Pool < T >
{/*** Returns an instance of type T from the pool.* * The call is a blocking call, * and client threads are made to wait* indefinitely until an object is available. * The call implements a fairness algorithm * that ensures that a FCFS service is implemented.* * Clients are advised to react to InterruptedException. * If the thread is interrupted while waiting * for an object to become available,* the current implementations * sets the interrupted state of the thread * to true and returns null. * However this is subject to change * from implementation to implementation.* * @return T an instance of the Object * of type T from the pool.*/T get();/*** Returns an instance of type T from the pool, * waiting up to the* specified wait time if necessary * for an object to become available..* * The call is a blocking call, * and client threads are made to wait* for time until an object is available * or until the timeout occurs. * The call implements a fairness algorithm * that ensures that a FCFS service is implemented.* * Clients are advised to react to InterruptedException. * If the thread is interrupted while waiting * for an object to become available,* the current implementations * set the interrupted state of the thread * to true and returns null. * However this is subject to change * from implementation to implementation.*  * * @param time amount of time to wait before giving up, *   in units of unit* @param unit a TimeUnit determining *   how to interpret the*        timeout parameter*        * @return T an instance of the Object * of type T from the pool.*        * @throws InterruptedException * if interrupted while waiting*/T get(long time, TimeUnit unit) throws InterruptedException;
}

我们的BoundedBlockingPool实现将如下所示:

package com.test.pool;import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;public final class BoundedBlockingPool < T > extends AbstractPool < T >implements BlockingPool < T >
{private int size;private BlockingQueue < T > objects;private Validator < T > validator;private ObjectFactory < T > objectFactory;private ExecutorService executor = Executors.newCachedThreadPool();private volatile boolean shutdownCalled;public BoundedBlockingPool(int size, Validator < T > validator, ObjectFactory < T > objectFactory){super();this.objectFactory = objectFactory;this.size = size;this.validator = validator;objects = new LinkedBlockingQueue < T >(size);initializeObjects();shutdownCalled = false;}public T get(long timeOut, TimeUnit unit){if(!shutdownCalled){T t = null;try{t = objects.poll(timeOut, unit);return t;}catch(InterruptedException ie){Thread.currentThread().interrupt();}return t;}throw new IllegalStateException('Object pool is already shutdown');}public T get(){if(!shutdownCalled){T t = null;try{t = objects.take();}catch(InterruptedException ie){Thread.currentThread().interrupt();}return t;}throw new IllegalStateException('Object pool is already shutdown');}public void shutdown(){shutdownCalled = true;executor.shutdownNow();clearResources();}private void clearResources(){for(T t : objects){validator.invalidate(t);}}@Overrideprotected void returnToPool(T t){if(validator.isValid(t)){executor.submit(new ObjectReturner(objects, t));}}@Overrideprotected void handleInvalidReturn(T t){}@Overrideprotected boolean isValid(T t){return validator.isValid(t);}private void initializeObjects(){for(int i = 0; i < size; i++){objects.add(objectFactory.createNew());}}private class ObjectReturner < E > implements Callable < Void >{private BlockingQueue < E > queue;private E e;public ObjectReturner(BlockingQueue < E > queue, E e){this.queue = queue;this.e = e;}public Void call(){while(true){try{queue.put(e);break;}catch(InterruptedException ie){Thread.currentThread().interrupt();}}return null;}}
}

上面是一个非常基本的对象池,在内部由LinkedBlockingQueue支持。 唯一感兴趣的方法是returnToPool()方法。 由于内部存储是一个阻塞池,因此如果我们尝试将返回的元素直接放入LinkedBlockingPool中,则如果队列已满,它可能会阻塞客户端。 但是我们不希望对象池的客户端仅为了执行普通任务(例如将对象返回到池)而阻塞。 因此,我们已经完成了将对象作为异步任务插入LinkedBlockingQueue的实际任务,并将其提交给Executor实例,以便客户端线程可以立即返回。

现在,我们将上述对象池用于代码中。 我们将使用对象池来池一些数据库连接对象。 因此,我们将需要一个验证器来验证我们的数据库连接对象。

我们的JDBCConnectionValidator将如下所示:

package com.test;import java.sql.Connection;
import java.sql.SQLException;import com.test.pool.Pool.Validator;public final class JDBCConnectionValidator implements Validator < Connection >
{public boolean isValid(Connection con){ if(con == null){return false;}try{return !con.isClosed();}catch(SQLException se){return false;}}public void invalidate(Connection con){try{con.close();}catch(SQLException se){}}
}

我们的JDBCObjectFactory将使对象池能够创建新对象,如下所示:

package com.test;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;import com.test.pool.ObjectFactory;public class JDBCConnectionFactory implements ObjectFactory < Connection >
{private String connectionURL;private String userName;private String password;public JDBCConnectionFactory(String driver, String connectionURL, String userName, String password){super();try{Class.forName(driver);}catch(ClassNotFoundException ce){throw new IllegalArgumentException('Unable to find driver in classpath', ce);}this.connectionURL = connectionURL;this.userName = userName;this.password = password;}public Connection createNew(){ try{return DriverManager.getConnection(connectionURL, userName, password);}catch(SQLException se){throw new IllegalArgumentException('Unable to create new connection', se);}}
}

现在,我们使用上面的Validator和ObjectFactory创建一个JDBC对象池:

package com.test;
import java.sql.Connection;import com.test.pool.Pool;
import com.test.pool.PoolFactory;public class Main
{public static void main(String[] args){Pool < Connection > pool = new BoundedBlockingPool < Connection > (10, new JDBCConnectionValidator(),new JDBCConnectionFactory('', '', '', ''));//do whatever you like}
}

作为阅读整个帖子的奖励。 我将提供Pool接口的另一种实现,它实际上是一个非阻塞对象池。 此实现与上一个实现的唯一区别是,如果某个元素不可用,则此实现不会阻塞客户端,而是返回null。 它去了:

package com.test.pool;import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.Semaphore;public class BoundedPool < T > extends AbstractPool < T >
{private int size;private Queue < T > objects;private Validator < T > validator;private ObjectFactory < T > objectFactory;private Semaphore permits;private volatile boolean shutdownCalled;public BoundedPool(int size, Validator < T > validator, ObjectFactory < T > objectFactory){super();this.objectFactory = objectFactory;this.size = size;this.validator = validator;objects = new LinkedList < T >();initializeObjects();shutdownCalled = false;}@Overridepublic T get(){T t = null;if(!shutdownCalled){if(permits.tryAcquire()){t = objects.poll();}}else{throw new IllegalStateException('Object pool already shutdown');}return t;}@Overridepublic void shutdown(){shutdownCalled = true;clearResources();}private void clearResources(){for(T t : objects){validator.invalidate(t);}}@Overrideprotected void returnToPool(T t){boolean added = objects.add(t);if(added){permits.release();}}@Overrideprotected void handleInvalidReturn(T t){}@Overrideprotected boolean isValid(T t){return validator.isValid(t);}private void initializeObjects(){for(int i = 0; i < size; i++){objects.add(objectFactory.createNew());}}
}

考虑到我们现在有两个强大的实现,最好让用户通过带有有意义名称的工厂创建我们的池。 这是工厂:

package com.test.pool;import com.test.pool.Pool.Validator;/*** Factory and utility methods for * {@link Pool} and {@link BlockingPool} classes * defined in this package. * This class supports the following kinds of methods:**
  • *
  • 创建并返回{@link Pool}接口的默认非阻塞*实现的方法。 *
  • * *
  • 创建并返回{@link BlockingPool}接口的默认实现的方法。 *
  • *
* * @author Swaranga * /公共最终类PoolFactory {private PoolFactory(){} / ** *创建一个并返回一个新的对象池,该对象池是{@link BlockingPool}的一个实现,其大小受以下限制: * size参数。 * * @param size池中对象的数量。 * @param factory工厂创建新对象。 * @param Validator验证器,用于验证返回对象的可重用性。 * * @返回一个受限制的对象池*由大小限制* / public static <T> Pool <T> newBoundedBlockingPool(int size,ObjectFactory <T> factory,Validator <T> validator){返回新的BoundedBlockingPool <T>(size,验证人,工厂); } / ** *创建一个并返回一个新的对象池,该对象池是{@link Pool}的一个实现,该对象的大小受size参数限制。 * * @param size池中对象的数量。 * @param factory工厂创建新对象。 * @paramvalidator验证器,以验证*返回对象的可重用性。 * * @返回一个受大小限制的对象池* / public static <T> Pool <T> newBoundedNonBlockingPool(int size,ObjectFactory <T> factory,Validator <T> validator){返回新的BoundedPool <T>(大小,验证器,厂); }}

因此,我们的客户现在可以以更易读的方式创建对象池:

package com.test;
import java.sql.Connection;import com.test.pool.Pool;
import com.test.pool.PoolFactory;public class Main
{public static void main(String[] args){Pool < Connection > pool = PoolFactory.newBoundedBlockingPool(10, new JDBCConnectionFactory('', '', '', ''), new JDBCConnectionValidator());//do whatever you like}
}

这样就结束了我们的长篇文章。 这个早就该了。 随时使用,更改,添加更多实现。

祝您编程愉快,别忘了分享!

参考: Java HotSpot博客上的JCG合作伙伴 Sarma Swaranga 提供的通用并发对象池 。


翻译自: https://www.javacodegeeks.com/2012/09/a-generic-and-concurrent-object-pool.html

并发加对象锁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353744.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringAOP02 自定义注解

1 自定义注解 1.1 创建自定义注解 从java5开始就可以利用 interface 来定义自定义注解 技巧01&#xff1a;注解不能直接干扰程序代码的运行&#xff08;即&#xff1a;注解的增加和删除操作后&#xff0c;代码都可以正常运行&#xff09; 技巧02&#xff1a;Retention 用来声明…

MFC处理回车窗口消失

MFC处理回车窗口消失 2011-04-24 12:21:31| 分类&#xff1a; C&C&VC | 标签&#xff1a;对话框 回车 mfc 消失 |字号大中小 订阅 我的方法是&#xff1a;找到自己设计的按钮&#xff0c;在属性-风格中选择default button&#xff1b;如果没有自己设计的but…

您的框架有多可扩展性?

在参加会议时&#xff0c;我们总是会见到高素质的决策者&#xff0c;他们经常问同样的问题&#xff1a; 您的框架有多可扩展性&#xff1f;如果我需要比您开箱即用的功能更多的东西怎么办&#xff1f; 。 这个问题是非常合理的&#xff0c;因为他们只是不想被卡在开发曲线的中间…

linux常用命令:touch 命令

linux的touch命令不常用&#xff0c;一般在使用make的时候可能会用到&#xff0c;用来修改文件时间戳&#xff0c;或者新建一个不存在的文件。 1&#xff0e;命令格式&#xff1a; touch [选项]... 文件... 2&#xff0e;命令参数&#xff1a; -a 或--timeatime或--timeacces…

用回车键实现MFC对话框中TAB键控件输入焦点在控件中跳转的效果(转)

用回车键实现MFC对话框中TAB键控件输入焦点在控件中跳转的效果&#xff08;转&#xff09; 版权声明&#xff1a;转载时请以超链接形式标明文章原始出处和作者信息及本声明 http://hcq11.blogbus.com/logs/54217707.html 近日在为一个数据应用写数据输入界面&#xff0c;大量…

python-面向对象编程设计与开发

编程范式 1、对不同类型的任务&#xff0c;所采取不同的解决问题的思路。 2、编程范式有两种 1、面向过程编程 2、面向对象编程 面向过程编程 什么是面向过程编程&#xff1f; 过程——解决问题的步骤 要解决一个大的问题 1、先把大问题拆分成若干小问题或子过程。 2、然后子过…

MFC下列表控件的使用

MFC下列表控件的使用 2012-11-09 16:46:57| 分类&#xff1a; 程序VC相关 | 标签&#xff1a; |字号大中小 订阅 1、应该加入头文件 #include <Atlbase.h>2、示例m_list.SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT|LVS_EX_ONECLICKACTIVATE);m_lis…

jbehave_使用JBehave,Gradle和Jenkins的行为驱动开发(BDD)

jbehave行为驱动开发 &#xff08;BDD&#xff09;是一个协作过程 &#xff0c;产品所有者&#xff0c;开发人员和测试人员可以合作交付可为业务带来价值的软件。 BDD是 测试驱动开发 &#xff08;TDD&#xff09; 的合理下一步 。 行为驱动的发展 本质上&#xff0c;BDD是一…

Confluence 6 考虑使用自定义 CSS

CSS 的知识储备 如果你没有有关 CSS 的相关知识&#xff0c;请参考页面 CSS Resources section 中的内容。当你打算开始对 Confluence 的样式表进行修改之前&#xff0c;你应该对 CSS 有一些相关的了解和知识储备。 安全 自定义 CSS 有可能被在页面中注入脚本&#xff0c;有跨…

MFC--CColorDialog的使用

MFC--CColorDialog的使用 2012-05-07 11:05:32| 分类&#xff1a; 学习mfc/c | 标签&#xff1a; |字号大中小 订阅 要在类中定义一个存储颜色的变量COLORREF m_color; 创建一个按钮&#xff0c;用来调用CColorDialog&#xff0c;用以改变静态文本的颜色&#xff0c;&a…

嵌入式 开发——DMA内存到外设

学习目标 加强理解DMA数据传输过程加强掌握DMA的初始化流程掌握DMA数据表查询理解源和目标的配置理解数据传输特点能够动态配置源数据学习内容 需求 串口发送数据 uint8_t data = 0x01; 串口发送(data); 实现串口的发送数据, 要求采用dma的方式 数据交互流程 CPU配置好DM…

使用Java第2部分查询DynamoDB项

在上一篇文章中&#xff0c;我们有机会发布了一些基本的DynamoDB查询操作。 但是&#xff0c;除了基本操作之外&#xff0c;DynamoDB api还为我们提供了一些额外的功能。 投影是具有类似选择功能的功能。 您选择应从DynamoDB项中提取哪些属性。 请记住&#xff0c;使用投影不…

XSS

1.什么是xss XSS攻击全称跨站脚本攻击&#xff0c;是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆&#xff0c;故将跨站脚本攻击缩写为XSS&#xff0c;XSS是一种在web应用中的计算机安全漏洞&#xff0c;它允许恶意web用户将代码植入到提供给其它用户使用的页面中…

C++中引用传递与指针传递区别(进一步整理)

C中引用传递与指针传递区别&#xff08;进一步整理&#xff09; 博客分类&#xff1a; C/C CCC#J# 从概念上讲。指针从本质上讲就是存放变量地址的一个变量&#xff0c;在逻辑上是独立的&#xff0c;它可以被改变&#xff0c;包括其所指向的地址的改变和其指向的地址中所存放的…

Python之匿名函数

一、匿名函数&#xff1a;也叫lambda表达式 1.匿名函数的核心&#xff1a;一些简单的需要用函数去解决的问题&#xff0c;匿名函数的函数体只有一行 2.参数可以有多个&#xff0c;用逗号隔开 3.返回值和正常的函数一样可以是任意的数据类型 二、匿名函数练习 请把下面的函数转换…

C++中const用法总结

C中const用法总结 Posted on 2009-04-21 22:55 月光林地 阅读(7821) 评论(2) 编辑 收藏 1. const修饰普通变量和指针 const修饰变量&#xff0c;一般有两种写法&#xff1a; const TYPE value; TYPE const value; 这两种写法在本质上是一样的。它的含义是&#xff1a;const修…

vaadin_5分钟内Google App Engine上的Vaadin App

vaadin在本教程中&#xff0c;您将学习如何创建第一个Vaadin Web应用程序&#xff0c;如何在本地AppEngine开发服务器上运行它以及如何将其部署到Google App Engine基础结构。 所有这些大约需要5到10分钟。 是的&#xff0c;如果您已经安装了必要的先决条件&#xff0c;则可以立…

【Java深入研究】10、红黑树

一、红黑树介绍 红黑树是二叉查找树&#xff0c;红黑树的时间复杂度为: O(lgn) 红黑树的特性&#xff1a;&#xff08;1&#xff09;每个节点或者是黑色&#xff0c;或者是红色。&#xff08;2&#xff09;根节点是黑色。&#xff08;3&#xff09;每个叶子节点&#xff08;NIL…

MATLAB排序函数

MATLAB排序函数 (2011-06-29 13:02:08) 源自网络 sort(A)若A是向量不管是列还是行向量&#xff0c;默认都是对A进行升序排列。sort(A)是默认的升序&#xff0c;而sort(A,descend)是降序排序。 sort(A)若A是矩阵&#xff0c;默认对A的各列进行升序排列 sort(A,dim) dim1时等效s…

【分形】【洛谷P1498】

https://www.luogu.org/problemnew/show/P1498 题目描述 自从到了南蛮之地&#xff0c;孔明不仅把孟获收拾的服服帖帖&#xff0c;而且还发现了不少少数民族的智慧&#xff0c;他发现少数民族的图腾往往有着一种分形的效果&#xff0c;在得到了酋长的传授后&#xff0c;孔明掌握…