Spring 使用 AOP+注解 来记录方法执行时间

一直以来都知道Spring支持一种叫做面向切面编程(AOP)的东西,但是一直都没有自己尝试使用过. 直到最近为了Debug方法,记录使用时间猛然发现AOP正好适合使用在这个场景下.为了灵活的使用AOP,我选择了使用注解来作为标记,当某个特定的注解被使用的时候将会自动触发这个切面.

1.注解的编写

package org.jzbk.rssplus.aspect.annotation;

import java.lang.annotation.*;

/**
 * Created by Kotarou on 2017/1/11.
 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Timed {
    boolean displayArgs() default false;
}

将注解设置为运行时RetentionPolicy.RUNTIME, 在编译时不会丢失这个注解信息.

设置注解主体为方法和类.

注解内部保存一个displayArgs的boolean变量,用于判断是否输出传入参数.

 

2. 编写AOP类

package org.jzbk.rssplus.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jzbk.rssplus.aspect.annotation.Timed;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * Created by Kotarou on 2017/1/11.
 */
@Aspect
@Component
public class TimedAOP {
    final private Logger logger = LoggerFactory.getLogger(getClass());

    @Pointcut("@annotation(org.jzbk.rssplus.aspect.annotation.Timed) || @target(org.jzbk.rssplus.aspect.annotation.Timed)")
    public void annotationProcessor() {
    }

    @Pointcut("execution(public * org.jzbk.rssplus..*.*(..))")
    public void publicMethod() {
    }

    @Around(value = "publicMethod() && annotationProcessor()")
    public Object count(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        final String methodName = proceedingJoinPoint.getSignature().getName();

        Long startTime = System.currentTimeMillis();
        Object result = proceedingJoinPoint.proceed();
        Long finishTime = System.currentTimeMillis();

        Signature signature = proceedingJoinPoint.getSignature();
        String[] packageName = signature.getDeclaringTypeName().split("\\.");
        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < packageName.length; ++i) {
            if (i < packageName.length - 1) {
                stringBuilder.append(packageName[i].substring(0, 1));
            } else {
                stringBuilder.append(packageName[i]);
            }
            stringBuilder.append(".");
        }

        logger.info("Executing: " + stringBuilder + signature.getName() + " took: " + (finishTime - startTime) + " ms");


        Method method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod();

        if (method.getDeclaringClass().isInterface()) {
            method = proceedingJoinPoint.getTarget().getClass().getDeclaredMethod(methodName, method.getParameterTypes());
        }

        // 方法上的注解优先级比类上的注解高,可以覆盖类上注解的值
        Timed timed = null;
        if (method.isAnnotationPresent(Timed.class)) {
            //处理方法上的注解
            timed = method.getAnnotation(Timed.class);
            if (timed.displayArgs()) {
                logArgs(proceedingJoinPoint.getArgs());
            }
        } else {
            //处理类上面的注解
            Object target = proceedingJoinPoint.getTarget();
            if (target.getClass().isAnnotationPresent(Timed.class)) {
                timed = target.getClass().getAnnotation(Timed.class);
                if (timed.displayArgs()) {
                    logArgs(proceedingJoinPoint.getArgs());
                }
            }
        }

        return result;
    }

    private void logArgs(Object[] args) {
        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < args.length; ++i) {
            stringBuilder.append("[");
            stringBuilder.append(i);
            stringBuilder.append("]: ");
            stringBuilder.append(args[i].toString());

            if (i < args.length - 1) {
                stringBuilder.append(", ");
            }
        }

        if (!stringBuilder.toString().isEmpty())
            logger.info("Argument List: " + stringBuilder);
        else
            logger.info("Argument List: Empty");
    }
}

 

AOP的切入点为使用了Timed的方法或者类.

方法上面的注解优先级比类上面的高,可以在方法上使用注解来覆盖掉类上注解的值.

 

演示:

在类上面增加注解,并设置displayArgs为true

 

在某个方式上覆盖注解冰将displayArgs设置为false

 

运行tomcat,查看日志

 

结果和期望中的一样.

Spring Boot加载Properties文件的方法

最近使用Spring Boot框架写了一个小网站.感觉Spring Boot写网站十分的优雅

本文将介绍如何在Spring Boot内引用Properties的值

1.开启文件扫描

2.在需要引入配置文件的Class上使用@PropertySource注解.

3.在Class中的属性上使用@Value注解来注入配置文件中的值.

 

演示

package org.jzbk.example.util;

import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

@Getter
@Component
@PropertySource(value = "classpath:versionInfo.properties")
public class VersionInfo {
    @Value("${example.platform}")
    private String platform;

    @Value("${example.version}")
    private String version;

    @Value("${example.branch}")
    private String branch;

    @Value("${example.buildDate}")
    private String buildDate;
}

 

Spring Session整合Redisson

前言:

Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service) Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。 (摘自官方WIKI)

 

Redisson在3.2.0版本里新增了对Spring-Session整合的支持.本文将介绍整合Spring-Boot Spring-Session Redisson的方法

1. 添加依赖

Maven

<dependency>
   <groupId>org.springframework.session</groupId>
   <artifactId>spring-session</artifactId>
   <version>1.2.2.RELEASE</version>
</dependency>
<dependency>
   <groupId>org.redisson</groupId>
   <artifactId>redisson</artifactId>
   <version>3.2.0</version>
</dependency>

 

Gradle

compile 'org.springframework.session:spring-session:1.2.2.RELEASE'  
compile group: 'org.redisson', name: 'redisson', version:'3.2.0'

 

2.创建配置文件RedisConfig.java

package org.jzbk.example.configuration;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.spring.session.config.EnableRedissonHttpSession;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;

@EnableRedissonHttpSession
public class RedisConfig {
    @Bean(destroyMethod = "shutdown")
    public RedissonClient getRedis() throws IOException {
        return Redisson.create(
                Config.fromYAML(
                        new ClassPathResource("redisson.yaml").getInputStream()
                )
        );
    }
}

因为我的redisson.yaml在classpath根目录下,所以直接使用ClassPathResource,请根据实际情况来修改.

 

3.修改application.properties,增加下列配置

spring.session.store-type=redis
server.session.timeout=7200

 

4.启动项目,刷新页面即可看到成功整合成功.

 

参考: https://github.com/redisson/redisson/wiki/14.-Integration%20with%20frameworks#145-spring-session

Spring Boot使用@Cacheable注解

通常,我使用Hibernate的@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)注解来缓存@Entity类.

在JAP2规范内另一个注解@Cacheable有与Hibernate的@Cache的一样的功能使用@Cacheable的条件如下.

1.Entity Class实现Serializable接口

2.在Entity Class前加入@Cacheable(true)

例如

@Entity
@Cacheable(true) 
public class UserEntity implements Serializable {
 // properties
}

 

3.在配置文件内开启缓存[1]

spring.jpa.properties.javax.persistence.sharedCache.mode=ENABLE_SELECTIVE

 

参考: http://docs.oracle.com/javaee/6/tutorial/doc/gkjio.html [1]

http://stackoverflow.com/questions/31585698/spring-boot-jpa2-hibernate-enable-second-level-cache

Visual Studio中的Console Application不显示Debug窗口

打开*.sln之后,在项目的属性页,“配置属性”/“链接器”/“系统”中“子系统”选择“Windows(/SUBSYSTEM:WINDOWS)原先为“控制台(/SUBSYSTEM:CONSOLE)”

如果只修改这一项,重新编译的时候会报这样的错误:
MSVCRTD.lib(crtexew.obj) : error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCRTStartup 中被引用

需要在“高级”选项中添加“入口点”:mainCRTStartup
再次编译就OK了。

C++实现的一个Order-List有序链表 带迭代器 模板类(class)

使用方法: 在项目中导入头文件
MYLIB::OrderedList<int> lists;
MYLIB::OrderedList<double> dlists;

P.S: 迭代器有点小问题

//
// Author: Kotarou.
// Email: t.k@07.gs
// FileName: OrderedList.h
// Last modify: 28/05/2015
//

#ifndef __ORDEREDLIST_H__
#define __ORDEREDLIST_H__
#include 
namespace MYLIB
{
	template
	class OrderedList;
	
	template 
	class ListNode
	{
		friend class OrderedList;
		friend class OrderedList::iterator;
		
		private:
			T Element;
			ListNode *prev;
			ListNode *next;
		public:
			ListNode() : next(NULL), prev(NULL) {};
	};
	
	template
	class OrderedList
	{
		private:
			ListNode *head;
			ListNode *tail;
		public:
			OrderedList() : head(NULL), tail(NULL) {};
			
			~OrderedList()
			{
				// delete all elements
				ListNode *temp = NULL;
				while(head)
				{
					temp = head->next;
					delete head;
					head = temp;
				}
			};
			
			// insertion sort
			void insert(const T &Element)
			{
				ListNode *temp = new ListNode;
				temp->Element = Element;
				
				if(!head && !tail)
				{
					head = temp;
					tail = temp;
				}
				else
				{
					//if the Element smaller than head, insert it before the head
					if(temp->Element <= head->Element)
					{
						temp->next = head;
						head->prev = temp;
						head = temp;
						return;
					}
					
					//if the Element greater than tail, insert it after the tail
					if(temp->Element >= tail->Element)
					{
						temp->prev = tail;
						tail->next = temp;
						tail = temp;
						return;
					}
					
					//find a position to insert
					ListNode *cur = head;
					while(cur)
					{
						if(temp->Element <= cur->Element)
						{
							temp->prev = cur->prev;
							cur->prev->next = temp;
							temp->next = cur;
							cur->prev = temp;
							break;
						}
						
						cur = cur->next;
					}
				}
			};
			
			class iterator
			{
				private:
					ListNode *node;
					bool done;
				public:
					iterator() : node(NULL), done(false) {};
					iterator(ListNode *in) : node(in), done(false){};
					
					T& operator*() // dereference
					{ 
						return node->Element; 
					};
					
					const T& operator*() const 
					{
						return node->Element; 
					};
					
					iterator& operator++() // prefix
					{
						node = node->next;
						return *this;
					};
					
					iterator operator++(int) // postfix
					{
						iterator temp = *this;
						++(*this);
						return temp;
					};
					
					iterator& operator--() // prefix
					{
						node = node->prev;
						return *this;
					};
					
					iterator operator--(int) // postfix
					{
						iterator temp = *this;
						--(*this);
						return temp;
					};
					
					bool operator==(const iterator& x) const
					{
						return (node == x.node);
					};
					
					bool operator!=(const iterator &rv)
					{
						if((node == rv.node && node) && done)
							return false;							
						
						if(node == rv.node && node)
							done = true;
						
						return ( node );
					};
			};
			
			iterator begin()
			{
				return iterator(head);
			};
			
			iterator end() 
			{
				return iterator(tail);
			};
	};
}
#endif


[C++]FCFS/RR/SJF/SRTF/RAND 调度算法模拟

一些进程调度算法的模拟.

输入参数:
./a.out 8 6 15 4

源代码:

#include 
#include 
#include 
#include 
#include 
using namespace std;
// some global value
int gMaxTimeInc, gMaxBurstTime;
int gNumProcesses, gTimeSlice;
struct Process
{
int ID;
int ArriveTime;
int WaitingTime;
int BurstTime;
int RunningTime;
int TurnAroundTime;
};
typedef deque dProcess;
void printResult(deque&, string*);
bool praseInput(int, const char**);
void getNextProcess(int&, int&);
bool isDigital(const char*);
char ganttChart(int);
dProcess generateJobQueue();
dProcess FCFS(dProcess, string&);
dProcess RR(dProcess, string&);
dProcess RAND(dProcess, string&);
dProcess SJF(dProcess, string&);
dProcess SRTF(dProcess, string&);
bool sortQueue (const Process &i,const Process &j) { return (i.ID list;
list.push_back(FCFS(Jobs,buffer[0]));
list.push_back(RR(Jobs,buffer[1]));
list.push_back(SJF(Jobs,buffer[2]));
list.push_back(SRTF(Jobs,buffer[3]));
list.push_back(RAND(Jobs,buffer[4]));
printResult(list, buffer);
}
else
{
cerr << "Invalid Argument, Try again.\n";
exit(EXIT_FAILURE);
}
return 0;
}
dProcess RAND(dProcess Jobs, string &chartBuffer)
{
unsigned long Time = 0;
bool done = false;
// get the job Queue.
dProcess ReadyQueue;
dProcess EndQueue;
Process* CPU = NULL;
//main loop for RAND.
for(; !done; ++Time)
{
//check the job queue, move job to the ready queue
for(dProcess::iterator it = Jobs.begin(); it != Jobs.end();)
{
if(Time >= it->ArriveTime)
{
ReadyQueue.push_back(*it);
it = Jobs.erase(it);
}
else
++it;
}
// move finished process to EndQueue
if(CPU && CPU->RunningTime == CPU->BurstTime)
{
CPU->TurnAroundTime += Time;
EndQueue.push_back(*CPU);
CPU = NULL;
}
//make the readyqueue randomly
random_shuffle(ReadyQueue.begin(), ReadyQueue.end());
// if all job finished, set done to true, skip all code.
if(EndQueue.size() == gNumProcesses)
{
done = true;
continue;
}
// check the ReadyQueue, move the first Process into CPU
if(CPU == NULL)
{
// if nothing in readyQueue, print -
if(!ReadyQueue.empty())
{
CPU = &ReadyQueue.front();
ReadyQueue.pop_front();
}
else
{
chartBuffer += "-";
continue;
}
}
else
{
for(dProcess::iterator it = ReadyQueue.begin(); it != ReadyQueue.end(); ++it)
{
if(it->ArriveTime != Time)
++it->WaitingTime;
}
}
if(CPU->RunningTime != CPU->BurstTime)
{
++CPU->RunningTime;
chartBuffer += ganttChart(CPU->ID);
}
}
return EndQueue;
}
dProcess SRTF(dProcess Jobs, string &chartBuffer)
{
unsigned long Time = 0;
bool done = false;
// get the job Queue.
dProcess ReadyQueue;
dProcess EndQueue;
Process* CPU = NULL;
//main loop for SRTF.
for(; !done; ++Time)
{
//check the job queue, move job to the ready queue
for(dProcess::iterator it = Jobs.begin(); it != Jobs.end();)
{
if(Time >= it->ArriveTime)
{
ReadyQueue.push_back(*it);
it = Jobs.erase(it);
}
else
++it;
}
// move finished process to EndQueue
if(CPU && CPU->RunningTime == CPU->BurstTime)
{
CPU->TurnAroundTime += Time;
EndQueue.push_back(*CPU);
CPU = NULL;
}
// if all job finished, set done to true, skip all code.
if(EndQueue.size() == gNumProcesses)
{
done = true;
continue;
}
//sort the ready queue
sort(ReadyQueue.begin(), ReadyQueue.end(), sortForSRTF);
// check the ReadyQueue, move the first Process into CPU
if(CPU == NULL)
{
// if nothing in readyQueue, print -
if(!ReadyQueue.empty())
{
CPU = &ReadyQueue.front();
ReadyQueue.pop_front();
}
else
{
chartBuffer += "-";
continue;
}
}
else
{
// check the ready queue.
if(!ReadyQueue.empty())
{
Process temp = ReadyQueue.front();
if(sortForSRTF(temp, *CPU))
{
ReadyQueue.push_back(*CPU);
CPU = &ReadyQueue.front();
ReadyQueue.pop_front();
}
}
for(dProcess::iterator it = ReadyQueue.begin(); it != ReadyQueue.end(); ++it)
{
if(it->ArriveTime != Time)
++it->WaitingTime;
}
}
if(CPU->RunningTime != CPU->BurstTime)
{
++CPU->RunningTime;
chartBuffer += ganttChart(CPU->ID);
}
}
sort(EndQueue.begin(), EndQueue.end(), sortQueue);
return EndQueue;
}
dProcess SJF(dProcess Jobs, string &chartBuffer)
{
unsigned long Time = 0;
bool done = false;
// get the job Queue.
dProcess ReadyQueue;
dProcess EndQueue;
Process* CPU = NULL;
//main loop for SJF.
for(; !done; ++Time)
{
//check the job queue, move job to the ready queue
for(dProcess::iterator it = Jobs.begin(); it != Jobs.end();)
{
if(Time >= it->ArriveTime)
{
ReadyQueue.push_back(*it);
it = Jobs.erase(it);
}
else
++it;
}
//sort the ready queue
sort(ReadyQueue.begin(), ReadyQueue.end(), sortForSJF);
// move finished process to EndQueue
if(CPU && CPU->RunningTime == CPU->BurstTime)
{
CPU->TurnAroundTime += Time;
EndQueue.push_back(*CPU);
CPU = NULL;
}
// if all job finished, set done to true, skip all code.
if(EndQueue.size() == gNumProcesses)
{
done = true;
continue;
}
// check the ReadyQueue, move the first Process into CPU
if(CPU == NULL)
{
// if nothing in readyQueue, print -
if(!ReadyQueue.empty())
{
CPU = &ReadyQueue.front();
ReadyQueue.pop_front();
}
else
{
chartBuffer += "-";
continue;
}
}
else
{
for(dProcess::iterator it = ReadyQueue.begin(); it != ReadyQueue.end(); ++it)
{
if(it->ArriveTime != Time)
++it->WaitingTime;
}
}
if(CPU->RunningTime != CPU->BurstTime)
{
++CPU->RunningTime;
chartBuffer += ganttChart(CPU->ID);
}
}
sort(EndQueue.begin(), EndQueue.end(), sortQueue);
return EndQueue;
}
dProcess RR(dProcess Jobs, string &chartBuffer)
{
unsigned long Time = 0;
bool done = false;
// get the job Queue.
dProcess ReadyQueue;
dProcess EndQueue;
Process* CPU = NULL;
//main loop for FCFS.
for(; !done; ++Time)
{
//check the job queue, move job to the ready queue
for(dProcess::iterator it = Jobs.begin(); it != Jobs.end();)
{
if(Time >= it->ArriveTime)
{
ReadyQueue.push_back(*it);
it = Jobs.erase(it);
}
else
++it;
}
// move finished process to EndQueue
if(CPU && CPU->RunningTime == CPU->BurstTime)
{
CPU->TurnAroundTime += Time;
EndQueue.push_back(*CPU);
CPU = NULL;
}
// push process back to the readyqueue
if(CPU && CPU->RunningTime != CPU->BurstTime && CPU->RunningTime % gTimeSlice == 0)
{
ReadyQueue.push_back(*CPU);
CPU = NULL;
}
// if all job finished, set done to true, skip all code.
if(EndQueue.size() == gNumProcesses)
{
done = true;
continue;
}
// check the ReadyQueue, move the first Process into CPU
if(CPU == NULL)
{
// if nothing in readyQueue, print -
if(!ReadyQueue.empty())
{
CPU = &ReadyQueue.front();
ReadyQueue.pop_front();
}
else
{
chartBuffer += "-";
continue;
}
}
else
{
for(dProcess::iterator it = ReadyQueue.begin(); it != ReadyQueue.end(); ++it)
{
if(it->ArriveTime != Time)
++it->WaitingTime;
}
}
if(CPU->RunningTime != CPU->BurstTime)
{
++CPU->RunningTime;
chartBuffer += ganttChart(CPU->ID);
}
}
sort(EndQueue.begin(),EndQueue.end(),sortQueue);
return EndQueue;
}
dProcess FCFS(dProcess Jobs, string &chartBuffer)
{
unsigned long Time = 0;
bool done = false;
// get the job Queue.
dProcess ReadyQueue;
dProcess EndQueue;
Process* CPU = NULL;
//main loop for FCFS.
for(; !done; ++Time)
{
//check the job queue, move job to the ready queue
for(dProcess::iterator it = Jobs.begin(); it != Jobs.end();)
{
if(Time >= it->ArriveTime)
{
ReadyQueue.push_back(*it);
it = Jobs.erase(it);
}
else
++it;
}
// move finished process to EndQueue
if(CPU && CPU->RunningTime == CPU->BurstTime)
{
CPU->TurnAroundTime += Time;
EndQueue.push_back(*CPU);
CPU = NULL;
}
// if all job finished, set done to true, skip all code.
if(EndQueue.size() == gNumProcesses)
{
done = true;
continue;
}
// check the ReadyQueue, move the first Process into CPU
if(CPU == NULL)
{
// if nothing in readyQueue, print -
if(!ReadyQueue.empty())
{
CPU = &ReadyQueue.front();
ReadyQueue.pop_front();
}
else
{
chartBuffer += "-";
continue;
}
}
else
{
for(dProcess::iterator it = ReadyQueue.begin(); it != ReadyQueue.end(); ++it)
{
if(it->ArriveTime != Time)
++it->WaitingTime;
}
}
if(CPU->RunningTime != CPU->BurstTime)
{
++CPU->RunningTime;
chartBuffer += ganttChart(CPU->ID);
}
}
return EndQueue;
}
void getNextProcess(int &ArrivalTime, int &BurstTime)
{
static int PrevTime=-1;
if(PrevTime == -1)
PrevTime = ArrivalTime = 0;
else
ArrivalTime = PrevTime + 1 + rand() % gMaxTimeInc;
BurstTime = 1 + rand() % gMaxBurstTime;
PrevTime = ArrivalTime;
}
dProcess generateJobQueue()
{
dProcess JobQueue;
for(int i = 0; i < gNumProcesses; ++i)
{
Process temp;
temp.ID = i;
temp.WaitingTime = 0;
temp.RunningTime = 0;
getNextProcess(temp.ArriveTime, temp.BurstTime);
temp.TurnAroundTime = 0 - temp.ArriveTime;
JobQueue.push_back(temp);
}
return JobQueue;
}
bool praseInput(int num, const char **input)
{
if(num < 5)
return false;
if(isDigital(input[1]) && isDigital(input[2]) && isDigital(input[3]) && isDigital(input[4]))
{
gNumProcesses = atoi(input[1]);
gMaxTimeInc = atoi(input[2]);
gMaxBurstTime = atoi(input[3]);
gTimeSlice = atoi(input[4]);
return true;
}
return false;
}
bool isDigital(const char *num)
{
size_t len = strlen(num);
for(size_t i = 0; i < len; ++i)
{
if(!isdigit(num[i]))
return false;
}
return true;
}
char ganttChart(int index)
{
while(index >= 62)
index -= 62;
if(index >= 0 && index <= 9)
return 48 + index;
else if(index >= 10 && index <= 35)
return 55 + index;
else if(index >= 36 && index <= 61)
return 61 + index;
return 0;
}
void printResult(deque &Queue, string *ChartArray)
{
printf("%16s%11s%13s%12s%12s\n","FCFS", "RR", "SJF", "SRTF", "RAND");
printf("%8s%5s%5s%7s%5s%7s%5s%7s%5s%7s%5s\n", "BT", "WT", "TT", "WT", "TT", "WT", "TT", "WT", "TT", "WT", "TT");
int waiting[5] = {}, turn[5] = {};
dProcess dp[5];
for(int i = 0; i < 5; ++i)
{
dp[i] = Queue.front();
Queue.pop_front();
}
for(int i = 0; i < gNumProcesses; ++i)
{
printf("P%-5d", i);
Process ps;
for(int j = 0; j < 5; ++j)
{
ps = dp[j].front();
dp[j].pop_front();
waiting[j] += ps.WaitingTime;
turn[j] += ps.TurnAroundTime;
if(j == 0)
printf("%-5d", ps.BurstTime);
printf("%-5d%-7d", ps.WaitingTime, ps.TurnAroundTime);
}
printf("\n");
}
printf("%-11s", "Average:");
for(int i = 0; i < 5; ++i)
{
printf("%-5d%-7d", waiting[i] / gNumProcesses, turn[i] / gNumProcesses);
}
printf("\n\n%-6s%s\n", "FCFS:", ChartArray[0].c_str());
printf("%-6s%s\n", "RR:", ChartArray[1].c_str());
printf("%-6s%s\n", "SJF:", ChartArray[2].c_str());
printf("%-6s%s\n", "SRTF:", ChartArray[3].c_str());
printf("%-6s%s\n", "RAND:", ChartArray[4].c_str());
}

运行结果:
QQ20151008-1@2x

[C++]使用循环输出图形(圆球)

话说这是某次assignment要求要的作业..
P.S: 代码不是我写的,是某个基友算出来的对应关系.

#include
using namespace std;
int main()
{
for (int i=1; i <= 6; i++)
{
for (int k = 1; k <= 10 - (-i*i + 7*i -2) / 2; k++)
cout << ' ';
for (int j = 1; j <= (-i*i + 7*i -2); j++)
{
if((j == 1)||(j == (-i*i + 7*i -2)))
cout << '*';
else
cout << ' ';
}
cout << endl;
}
}

效果图:
20131106220340

[C++]10进制转换二进制(带计算过程)

某次的作业需要我们做10进制到2进制/8进制的转换为了偷懒就随手谢了下面的东西.

#include
using namespace std;
int main()
{
const int BASE = 2;
unsigned long num  = 0;
int binaryNum[64] = {0};
cout << "Enter a number: ";
cin >> num;
if(!cin.fail() && num > 0)
{
int numMod = 0, length = 0;
while(num != 0)
{
numMod = num % BASE;
binaryNum[length++] = numMod;
cout << num << " / " <<  BASE << " = " <<
num / BASE << " + " << numMod << endl;
num /= BASE;
}
cout << endl  << "Length: " << length << endl;
cout << "Result: ";
for(int i = length-1; i >= 0; i--)
cout << binaryNum[i];
cout << endl;
}
else
cerr << "Wrong Input.\n";
return 0;
}

效果图:
20131106214952

[转]Linux下gcc编译生成动态链接库*.so文件并调用它

动态库*.so在linux下用c和c++编程时经常会碰到,最近在网站找了几篇文章介绍动态库的编译和链接,总算搞懂了这个之前一直不太了解得东东,这里做个笔记,也为其它正为动态库链接库而苦恼的兄弟们提供一点帮助。
1、动态库的编译

下面通过一个例子来介绍如何生成一个动态库。这里有一个头文件:so_test.h,三个.c文件:test_a.c、test_b.c、test_c.c,我们将这几个文件编译成一个动态库:libtest.so。

//so_test.h:
#include “stdio.h”
void test_a();
void test_b();
void test_c();

//test_a.c:
#include “so_test.h”
void test_a()
{
 printf(“this is in test_a…\n”);
}

//test_b.c:
#include “so_test.h”
void test_b()
{
 printf(“this is in test_b…\n”);
}

//test_c.c:
#include “so_test.h”
void test_c()
{
 printf(“this is in test_c…\n”);
}
将这几个文件编译成一个动态库:libtest.so
$ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so

2、动态库的链接
在1、中,我们已经成功生成了一个自己的动态链接库libtest.so,下面我们通过一个程序来调用这个库里的函数。程序的源文件为:test.c。

test.c:
#include “so_test.h”
int main()
{
test_a();
test_b();
test_c();
return 0;
}
将test.c与动态库libtest.so链接生成执行文件test:
$ gcc test.c -L. -ltest -o test
测试是否动态连接,如果列出libtest.so,那么应该是连接正常了
$ ldd test
执行test,可以看到它是如何调用动态库中的函数的。
3、编译参数解析
最主要的是GCC命令行的一个选项:
-shared该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件

-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。

-L.:表示要连接的库在当前目录中

-ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称

LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。

当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。

4、注意

调用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。

在linux下可以用export命令来设置这个值,在linux终端下输入:
export LD_LIBRARY_PATH=/opt/au1200_rm/build_tools/bin: $LD_LIBRARY_PATH:
然后再输入:export
即会显示是否设置正确
export方式在重启后失效,所以也可以用 vim /etc/bashrc ,修改其中的LD_LIBRARY_PATH变量。
例如:LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/au1200_rm/build_tools/bin。

 

转自:http://blog.sina.com.cn/s/blog_54f82cc20101153x.html