Истеризация потоков из управляемого управляемого сеанса компонента не обязательно является хаком, если она выполняет задание, которое вы хотите. Но нерестовые потоки при необходимости должны выполняться с особой осторожностью. Код не должен записываться таким образом, чтобы один пользователь мог, например, создать неограниченное количество потоков за сеанс и / или продолжить работу потоков даже после того, как сеанс будет уничтожен. Это рано или поздно взорвет ваше приложение.
Код должен быть написан таким образом, чтобы вы могли убедиться, что пользователь может, например, никогда не создавать более одного фонового потока за сеанс и гарантировать поток чтобы прерваться всякий раз, когда сессия будет уничтожена. Для выполнения нескольких задач в сеансе вам необходимо поставить в очередь задачи.
Кроме того, все эти потоки должны предпочтительно обслуживаться общим пулом потоков, чтобы вы могли наложить ограничение на общее количество порожденных потоков на уровне приложения. Средний сервер приложений Java EE предлагает пул потоков, управляемый контейнером, который вы можете использовать, среди прочих, EJB @Asynchronous
и @Schedule
. Чтобы быть независимым от контейнера, вы также можете использовать Util Concurrent ExecutorService
и ScheduledExecutorService
для Java 1.5.
Ниже приведены примеры Java EE 6+ с EJB.
@Named
@RequestScoped // Or @ViewScoped
public class Bean {
@EJB
private SomeService someService;
public void submit() {
someService.asyncTask();
// ... (this code will immediately continue without waiting)
}
}
@Stateless
public class SomeService {
@Asynchronous
public void asyncTask() {
// ...
}
}
@Named
@RequestScoped // Or @ViewScoped
public class Bean {
private Future> asyncEntities;
@EJB
private EntityService entityService;
@PostConstruct
public void init() {
asyncEntities = entityService.asyncList();
// ... (this code will immediately continue without waiting)
}
public List getEntities() {
try {
return asyncEntities.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new FacesException(e);
} catch (ExecutionException e) {
throw new FacesException(e);
}
}
}
@Stateless
public class EntityService {
@PersistenceContext
private EntityManager entityManager;
@Asynchronous
public Future> asyncList() {
List entities = entityManager
.createQuery("SELECT e FROM Entity e", Entity.class)
.getResultList();
return new AsyncResult<>(entities);
}
}
Если вы используете библиотечную утилиту JSF OmniFaces , это можно сделать еще быстрее, если вы аннотируете управляемый компонент с помощью @Eager
.
@Singleton
public class BackgroundJobManager {
@Schedule(hour="0", minute="0", second="0", persistent=false)
public void someDailyJob() {
// ... (runs every start of day)
}
@Schedule(hour="*/1", minute="0", second="0", persistent=false)
public void someHourlyJob() {
// ... (runs every hour of day)
}
@Schedule(hour="*", minute="*/15", second="0", persistent=false)
public void someQuarterlyJob() {
// ... (runs every 15th minute of hour)
}
@Schedule(hour="*", minute="*", second="*/30", persistent=false)
public void someHalfminutelyJob() {
// ... (runs every 30th second of minute)
}
}
@Named
@RequestScoped // Or @ViewScoped
public class Bean {
@EJB
private SomeTop100Manager someTop100Manager;
public List getSomeTop100() {
return someTop100Manager.list();
}
}
@Singleton
@ConcurrencyManagement(BEAN)
public class SomeTop100Manager {
@PersistenceContext
private EntityManager entityManager;
private List top100;
@PostConstruct
@Schedule(hour="*", minute="*/1", second="0", persistent=false)
public void load() {
top100 = entityManager
.createNamedQuery("Some.top100", Some.class)
.getResultList();
}
public List list() {
return top100;
}
}
Вы можете использовать функцию order ()
напрямую, не прибегая к дополнительным инструментам - см. Этот более простой ответ, в котором используется трюк прямо из верхней части ] пример (порядок)
код:
R> dd[with(dd, order(-z, b)), ]
b x y z
4 Low C 9 2
2 Med D 3 1
1 Hi A 8 1
3 Hi A 9 1
Редактировать через 2+ года: Просто спросили, как это сделать по индексу столбца. Ответ состоит в том, чтобы просто передать желаемый столбец сортировки в функцию order ()
:
R> dd[order(-dd[,4], dd[,1]), ]
b x y z
4 Low C 9 2
2 Med D 3 1
1 Hi A 8 1
3 Hi A 9 1
R>
, а не использовать имя столбца (и с ()
для упрощения / более прямой доступ).
В качестве альтернативы, используя пакет Deducer
library(Deducer)
dd<- sortData(dd,c("z","b"),increasing= c(FALSE,TRUE))
С помощью этой (очень полезной) функции Кевина Райта , размещенной в разделе советов вики-сайта R, этого легко добиться.
sort(dd,by = ~ -z + b)
# b x y z
# 4 Low C 9 2
# 2 Med D 3 1
# 1 Hi A 8 1
# 3 Hi A 9 1
Или вы можете использовать пакет доб
library(doBy)
dd <- orderBy(~-z+b, data=dd)
если SQL для вас естественен, sqldf
пакет обрабатывает ORDER BY
как и предполагал Кодд.