public class Topu{
private Map<Integer,List<Integer>> map = new HashMap<>();
private List<List<Integer,Integer>> side = new ArrayList<>(){{}};
private int[] in_degree = new int[n];
private List<Integer> queue = new ArrayList<>();
public void creat_linkedlist(){
for(int i = 0 ; i < side.length; i++){
List<Integer,Integer> cur = side.get(i);
if(map.get(cur.get(0))==null){
map.put(cur.get(0),new ArrayList<Integer>());
}
map.get(cur.get(0)).add(cur.get(1));
in_degree[cur.get(1)]++;
}
for(int i = 0 ; i < in_degree.length; i++){
if(in_degree[i]==0){
queue.add(i);
}
}
}
public List<Integer> tuopu(){
List<Integer> list = new ArrayList<Integer>();
while(!queue.isEmpty()){
int cur = queue.remove(0);
list.add(cur);
List<Integer> list = map.get(cur);
for(int a : list){
in_degree[a]--;
if(in_degree[a]==0){
queue.add(a);
}
}
}
return list;
}
}
<!-- Snippets only -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/>
</parent>
<properties>
<servicebus.version>2.1.6</servicebus.version>
</properties>
<!--
Use later version of azure-servicebus than that provided by
azure-servicebus-spring-boot-starter (optional)
-->
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-servicebus</artifactId>
<version>1.2.11</version>
</dependency>
<!--
Azure Boot Starter for Service Bus
https://mvnrepository.com/artifact/com.microsoft.azure/azure-servicebus-spring-boot-starter
-->
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-servicebus-spring-boot-starter</artifactId>
<version>${servicebus.version}</version>
</dependency>
application.properties
# Topic
azure.servicebus.topic-name=x-events
# Queue
azure.servicebus.queue-name=x-mailer
azure.servicebus.queue-receive-mode=peeklock
# Subscribe to Topic
azure.servicebus.subscription-name=appian
azure.servicebus.subscription-receive-mode=peeklock
# Service Bus Connection String (without Key Vault)
azure.servicebus.connection-string=Endpoint=sb://sb-doubledecker-ric-eun.servicebus.windows.net/;SharedAccessKeyName=x-events-send-listen;SharedAccessKey=KmsawwhktZgY8gfb7g1rH6iXNJv9Kr3r1pLWol3o2Ik=;EntityPath=x-events
# & with Key Vault (making sure the key vault key name is unique)
azure.servicebus.connection-string=${events-servicebus-connectionstring}
TopicPublisher.java
@Component
@Slf4j
public class EventTopicPublisher {
private TopicClient topicClient;
private TelemetryClient telemetry;
public EventTopicPublisher(TopicClient topicClient, TelemetryClient telemetry) {
this.topicClient = topicClient;
this.telemetry = telemetry;
}
boolean publishTopicMessage(String code, String messageBody) {
log.debug("Sending event: {} of type '{}'", messageBody, code);
final Message message = new Message(messageBody, MediaType.APPLICATION_JSON_VALUE);
Map<String, String> props = new HashMap<>();
props.put("X-Event-Code", code);
message.setProperties(props);
boolean success = false;
long startTime = System.currentTimeMillis();
try {
topicClient.send(message);
success = true;
} catch (InterruptedException | ServiceBusException e) {
telemetry.trackException(e);
} finally {
Duration delta = new Duration(System.currentTimeMillis() - startTime);
RemoteDependencyTelemetry dependency = new RemoteDependencyTelemetry("x-events", "send", delta, success);
dependency.setType("Azure Service Bus");
telemetry.trackDependency(dependency);
}
return success;
}
@PreDestroy
public void shutdown() throws ServiceBusException {
log.debug("Shutting down, closing topic client {}", topicClient.getTopicName());
topicClient.close();
}
}
TopicSubscriber.java
@Component
@Slf4j
public class AppianTopicSubscriber implements IMessageHandler {
private TopicClient topicClient;
private SubscriptionClient subscriptionClient;
private TelemetryClient telemetry;
public AppianTopicSubscriber(TopicClient topicClient, SubscriptionClient subscriptionClient, TelemetryClient telemetry) {
this.topicClient = topicClient;
this.subscriptionClient = subscriptionClient;
this.telemetry = telemetry;
}
@PostConstruct
public void startup() throws ServiceBusException, InterruptedException {
// start receiving messages
ExecutorService executorService = Executors.newCachedThreadPool();
subscriptionClient.registerMessageHandler(this, new MessageHandlerOptions(1, false, ofMinutes(1)), executorService);
}
/**
* The callback that the message pump uses to pass received Messages to the app.
*
* @param message received message
*/
@Override
public CompletableFuture<Void> onMessageAsync(IMessage message) {
final String messageBody = new String(message.getBody(), UTF_8);
boolean success = false;
long startTime = System.currentTimeMillis();
try {
log.debug("Received message from topic: '{}'", messageBody);
success = processMessageInSomeWay(messageBody);
if (success) {
subscriptionClient.complete(message.getLockToken());
}
else {
subscriptionClient.abandon(message.getLockToken());
}
} catch (InterruptedException | ServiceBusException e) {
telemetry.trackException(e);
} finally {
trackServiceBusTelemetry(success, startTime);
}
return completedFuture(null);
}
private void trackServiceBusTelemetry(boolean success, long startTime) {
Duration delta = new Duration(System.currentTimeMillis() - startTime);
RemoteDependencyTelemetry dependency = new RemoteDependencyTelemetry("x-events", "receive", delta, success);
dependency.setType("Azure Service Bus");
telemetry.trackDependency(dependency);
}
@Override
public void notifyException(Throwable exception, ExceptionPhase phase) {
ExceptionTelemetry et = new ExceptionTelemetry(exception);
et.setSeverityLevel(SeverityLevel.Critical);
telemetry.trackException(et);
}
@PreDestroy
public void shutdown() throws ServiceBusException {
topicClient.close();
}
}
基于:<br/> - Spring Boot 1.5 <br/> - Spring 4.3 <br/> - Spring Data JPA 1.11(Ingalls)<br/> - Hibernate 5.0
Entity.java
@Entity
@EntityListeners(AuditingEntityListener.class)
@Table(name = "EFE_MESSAGES")
@Where(clause = "EMS_DATE_TIME > '01-JAN-2015'")
@GenericGenerator(name = "increment",strategy = "increment")
// Lombok method generators
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
// Ensures commencesOnDate is earlier than expiresAfterDate
// @MessageDateRange
@ScriptAssert(lang ="javascript", script ="_this.validateStartBeforeEnd()", message = "The start date must be at least one day before the expiry date")
public class Message {
/**
* The <code>EMS_NUMBER</code>column is used as the PK, and maintained using MAX+1 strategy -
* see the Hibernate-specific {@link GenericGenerator}<code>increment</code>annotation.
*/
@Id
@Builder.Default
@Column(name = "EMS_NUMBER")
@Setter(AccessLevel.PROTECTED)
@GeneratedValue(generator = "increment")
private Long id = null;
@CreatedDate
@Column(name = "EMS_DATE_TIME")
@DateTimeFormat(iso = ISO.DATE)
private LocalDate createdDate;
@CreatedBy
@Column(name ="EMS_ADDED_BY")
private String addedBy;
@Column(name ="EMS_TARGET_USER")
private String targetUser;
@DateTimeFormat(iso = ISO.DATE)
@Column(name = "EMS_COMMENCEMENT_DATE")
@NotNull(message = "The start date must be specified")
private LocalDate commencesOnDate;
@NotNull
@NonNull
@Column(name = "EMS_MESSAGE_TYPE")
@Enumerated(EnumType.STRING)
private MessageTypetype;
public boolean isNew() {
return getId() == null;
}
/**
* Used by the Hibernate-specific {@link ScriptAssert} annotation on this class.
*
* @return true if the commencement date is before the end date, or if either of the dates are
* null (null values preclude proper validation).
*/
public boolean validateStartBeforeEnd() {
// Ignore if either of the dates are null, as the validation can't be made
if (getCommencesOnDate() == null || getExpiresAfterDate() == null ) return true;
return getCommencesOnDate().isBefore(getExpiresAfterDate());
}
public boolean isCurrent() {
return getNullSafeExpiresAfterDate().isAfter(LocalDate.now()) && getNullSafeCommencesOnDate().isBefore(LocalDate.now().plusDays(1));
}
}
JpaConfig.java
@Configuration
@PropertySource("classpath:jpa-${spring.profiles.active}.properties")
// Trigger Spring Data JPA goodness
@EnableJpaRepositories
// Enable auditing of who creates/updates an Entity and when
@EnableJpaAuditing
// For jsr310 java 8 java.time.*
// Configures the base packages used by auto-configuration when scanning for entity classes.
@EntityScan(basePackageClasses = { Message.class, Jsr310JpaConverters.class })
public class JpaConfig {
/**
* Bean for allowing the Jpa Auditing feature to access the authenticated user's username.
*/
@Bean
public AuditorAware<String> auditorProvider() {
return new SpringSecurityAuditorAware();
}
/**
* @return configuration for the {@link #appDataSource()} for the {@link Message} domain model.
* The properties come from <code>application.properties</code>.
*/
@Bean
@Primary
@ConfigurationProperties("datasource.app")
public DataSourceProperties appDataSourceProperties() {
return new DataSourceProperties();
}
@Primary
@Bean("dataSource")
@ConfigurationProperties("datasource.app")
public DataSource appDataSource() {
return appDataSourceProperties().initializeDataSourceBuilder().build();
}
/**
* @return configuration for the {@link #securityDataSource()} for the security infrastructure.
* The properties come from <code>application.properties</code>.
*/
@Bean
@ConfigurationProperties("datasource.security")
public DataSourceProperties securityDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@ConfigurationProperties("datasource.security")
public DataSource securityDataSource() {
return securityDataSourceProperties().initializeDataSourceBuilder().build();
}
}
Repo.java
import java.time.LocalDate;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import com.hansard.messaging.domain.Message;
import com.hansard.messaging.domain.QMessage;
import com.querydsl.core.types.dsl.BooleanExpression;
/**
* Spring Data JPA repository interface (no implementation required) for {@link Message}.
*
* <p>
* The {@link QueryDslPredicateExecutor} is used in conjunction with Maven artifact
* <code>com.querydsl.querydsl-jpa</code>. The corresponding {@link QMessage} class is generated to
* <code>target/generated-sources/java</code>.
*
* <p>
* A few DSL Expressions are implemented here for convenience. See {@link #isCurrent()} etc.
*
* @author Richard Cowin
*/
public interface MessageRepository extends JpaRepository<Message, Long>, QueryDslPredicateExecutor<Message> {
// Effectively "where UPPER(messageHtml) like '%UPPER(textToSearch)%'"
static BooleanExpression messageContains(String textToSearch) {
return QMessage.message.messageHtml.containsIgnoreCase(textToSearch);
}
static BooleanExpression isExpired() {
return QMessage.message.expiresAfterDate.loe(LocalDate.now());
}
static BooleanExpression isPending() {
return QMessage.message.commencesOnDate.after(LocalDate.now());
}
static BooleanExpression isCurrent() {
BooleanExpression beforeExpiry = QMessage.message.expiresAfterDate.after(LocalDate.now());
BooleanExpression afterCommencement = QMessage.message.commencesOnDate.loe(LocalDate.now());
return beforeExpiry.and(afterCommencement);
}
}
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package alt.android.os;
import android.util.Log;
import android.os.Handler;
import android.os.SystemClock;
import android.os.Message;
/**
* Schedule a countdown until a time in the future, with
* regular notifications on intervals along the way.
*
* Example of showing a 30 second countdown in a text field:
*
* <pre class="prettyprint">
* new CountdownTimer(30000, 1000) {
*
* public void onTick(long millisUntilFinished) {
* mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
* }
*
* public void onFinish() {
* mTextField.setText("done!");
* }
* }.start();
* </pre>
*
* The calls to {@link #onTick(long)} are synchronized to this object so that
* one call to {@link #onTick(long)} won't ever occur before the previous
* callback is complete. This is only relevant when the implementation of
* {@link #onTick(long)} takes an amount of time to execute that is significant
* compared to the countdown interval.
*/
public abstract class CountDownTimer {
/**
* Millis since epoch when alarm should stop.
*/
private final long mMillisInFuture;
/**
* The interval in millis that the user receives callbacks
*/
private final long mCountdownInterval;
private long mStopTimeInFuture;
private boolean mCancelled = false;
/**
* @param millisInFuture The number of millis in the future from the call
* to {@link #start()} until the countdown is done and {@link #onFinish()}
* is called.
* @param countDownInterval The interval along the way to receive
* {@link #onTick(long)} callbacks.
*/
public CountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
}
/**
* Cancel the countdown.
*
* Do not call it from inside CountDownTimer threads
*/
public final void cancel() {
mHandler.removeMessages(MSG);
mCancelled = true;
}
/**
* Start the countdown.
*/
public synchronized final CountDownTimer start() {
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
mCancelled = false;
return this;
}
/**
* Callback fired on regular interval.
* @param millisUntilFinished The amount of time until finished.
*/
public abstract void onTick(long millisUntilFinished);
/**
* Callback fired when the time is up.
*/
public abstract void onFinish();
private static final int MSG = 1;
// handles counting down
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
synchronized (CountDownTimer.this) {
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
if (millisLeft <= 0) {
onFinish();
} else if (millisLeft < mCountdownInterval) {
// no tick, just delay until done
sendMessageDelayed(obtainMessage(MSG), millisLeft);
} else {
long lastTickStart = SystemClock.elapsedRealtime();
onTick(millisLeft);
// take into account user's onTick taking time to execute
long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
// special case: user's onTick took more than interval to
// complete, skip to next interval
while (delay < 0) delay += mCountdownInterval;
if (!mCancelled) {
sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
}
};
}