最近在学习java,不过一直是在windows的eclipse上做开发。服务器一般都是linux,所以得部署到Linux系统上。eclipse是有linux版本的,但不在本文所讨论的范围内。本文主要是讲讲如何通过脚本编译和运行java程序的。
1、 编译命令
javac [-d] [-o] [-verbose] [-classpath][-sourcepath]
1) -d, 指定生成的.class文件存放目录,一般省略则默认放在java源文件同一目录下
2)-o, 这个选项告诉javac优化内联的static,final以及privite成员函数所产生的码。
3) -verbose,此选项告知java显示出有关被编译的源文件和任何被调用类库的信息。如-verbose:class能看到各种加载的信息,-verbose:gc 是garbagecollection 的信息
4)-classpath,设定要用到的类路径,可以是目录,jar文件,zip文件(里面都是class文件),值得注意的是,此classpath中的内容是会覆盖掉环境变量CLASSPATH里面的设定。也可以省略,省略则默认使用环境变量$CLASSPATH路径。所以一般classpath的设定都是:当前目录加环境变量CLASSPATH设置目录,如javac -classpath .:$CLASSPATH abc.java java基本类一般都在JDK环境变量$CLASSPATH中指定好路径了自己需要用到的第三方类一般都放在文件当前目录下,用.指定路径即可
若自己需要添加一些类可以在.:$CLASSPATH后面添加“:类的具体路径”。
5)-sourcepath, 设定要编译的java文件路径,可以是目录,jar文件,zip文件(里面都是java文件)。
若编译的是jar包中的主类文件abc.java时,一般编译整个包javac edu.test.jar或者包文件夹javac ./edu/test。
一般当java文件中有多个需要编译时,可以逐一列出,也可以将文件名列在一个文件中,名称间用空格或者回车行来进行分隔,然后在命令行中使用该列表名,名字前冠以@字符。
说明
1)一般,对于只有一个出口主函数main,其他java文件是以内联类的形式被主函数调用的多个java文件组成的工程来说,编译时只需要对出口主函数main所在java文件编译即可,工程中的其他java文件会自动关联编译。
2)对于程序中调用到了第三方类或者package的情况,则一般先需要在程序文件中加入import第三方类或者jar包.* 如
import edu.test.abc 引用jar包edu.test下的abc.java,如果直接引用文件夹的话,则是edu/test文件夹下的abc.java文件。为稳妥,一般都引用整个包内文件import edu.test.*。(jar包名对应文件夹路径,将某个路径文件夹下的所有java文件进行打包即为jar包,引用时可以直接引用文件夹)编译时需要将jar包路径或者文件夹根目录,如edu的路径加入到classpath中。一般常把jar包或者根文件夹拷贝到当前目录下,指定classpath为.,编译器自动会从当前目录开始寻找。
2、运行
java [-classpath] [-sourcepath]
1)-classpath和编译时一致,指定运行时要搜索的类路径。需要注意的是,由于所要执行的类也是要搜索的类的一部分,所以一定要把这个类的路径也放到classpath设置里,故在要执行的类的路径里执行java命令时,一定要加上.表示当前目录也搜索。
2)-sourcepath 指需要运行的目标文件名(不要后缀名),如编译javac a.java则运行java a。若运行的是jar包中的主类文件时需要指出包路径并要在class名前带上完整的包名,如java edu,test.abc。且该包的根目录(edu所在文件夹路径)需要包含在classpath中。
说明:
1)文件搜索时,系统只会向下,从指定目录向其子目录搜索,不会溯源向其父祖目录搜索。
2)运行时,classpath应同时包含执行的目录和调用类的目录,一般两者放在同一根目录下,运行时在根目录下运行。不然会出现错误找不到运行的main函数。如调用的类文件./com/bao/ws/h.class,执行文件为./com/bao/bs/a.class,classpath应包含.路径
运行环境:ubuntu系统14.04
java version "1.8.0_181"
Redis server v=2.8.4
1、下图左是我在elipse写好的redis测试生产消费模型项目,下图右是我在ubuntu系统里边运行后的目录结构。
2、代码
1)TaskConsumer.java(redis消费)
package scheduleTest;
import java.util.Random;
import redis.clients.jedis.Jedis;
public class TaskConsumer implements Runnable {
Jedis jedis = new Jedis("127.0.0.1",6379);
public void run() {
Random random = new Random();
while(true){
//从任务队列"task-queue"中获取一个任务,并将该任务放入暂存队列"tmp-queue"
String taskid = jedis.rpoplpush("task-queue", "tmp-queue");
// 处理任务----纯属业务逻辑,模拟一下:睡觉
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//模拟成功和失败的偶然现象
if(random.nextInt(13) % 7 == 0){// 模拟失败的情况,概率为2/13
//将本次处理失败的任务从暂存队列"tmp-queue"中,弹回任务队列"task-queue"
jedis.rpoplpush("tmp-queue", "task-queue");
System.out.println(taskid + "处理失败,被弹回任务队列");
} else {// 模拟成功的情况
// 将本次任务从暂存队列"tmp-queue"中清除
jedis.rpop("tmp-queue");
System.out.println(taskid+"处理成功,被清除");
}
}
}
}
2)TaskProducer.java
package scheduleTest;
import java.util.Random;
import java.util.UUID;
import redis.clients.jedis.Jedis;
public class TaskProducer implements Runnable{
Jedis jedis = new Jedis("127.0.0.1",6379);
public void run() {
Random random = new Random();
while(true){
try{
Thread.sleep(random.nextInt(600) + 600);
// 模拟生成一个任务
UUID taskid = UUID.randomUUID();
//将任务插入任务队列:task-queue
jedis.lpush("task-queue", taskid.toString());
System.out.println("插入了一个新的任务: " + taskid);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
3)TaskShedulerSystem.java
package scheduleTest;
public class TaskShedulerSystem {
public static void main(String[] args) throws Exception {
// 启动一个生产者线程,模拟任务的产生
new Thread(new TaskProducer()).start();
Thread.sleep(15000);
//启动一个线程者线程,模拟任务的处理
new Thread(new TaskConsumer()).start();
//主线程休眠
Thread.sleep(Long.MAX_VALUE);
}
}
上边的代码文件引用关系已经能通过代码看出来了。TaskShedulerSystem.java调用TaskProducer.java和TaskConsumer.java 。下边的过程就得对现有程序进行编译和运行了。
java编译用javac,运行用java命令这肯定是没跑的。一条一条去编译执行显然不适合java项目(多个java文件并存在引用情况)。这里很自然会想到编写编译脚本和运行脚本来完成java项目的编译和运行工作。我用的是shell脚本,有兴趣的也可以尝试其他脚本语言实现。
1、编译脚本
make.sh
#!/bin/bash
# Get current position
TOP_DIR=bin/
# Add all necessary jars
LIBPATH=lib/jedis-2.1.0.jar
#compile java file
javac -encoding utf-8 -cp $LIBPATH src/scheduleTest/TaskProducer.java -d bin/
javac -encoding utf-8 -cp $LIBPATH src/scheduleTest/TaskConsumer.java -d bin/
javac -encoding utf-8 -cp $TOP_DIR src/scheduleTest/TaskShedulerSystem.java -d bin/
注:编译后会在bin文件夹下生成scheduleTest文件夹 ,进入到该文件夹你会发现,里边躺着你编译过的3个.class文件。
2、运行文件run
#!/bin/bash
# Get current position
TOP_DIR=bin/
# Add all necessary jars
LIBPATH=lib/jedis-2.1.0.jar
#run program
java -cp $TOP_DIR:$LIBPATH scheduleTest.TaskShedulerSystem
3、运行效果
本文用的实例需要用到redis内存数据库,如果不想弄得这么复杂的话可以看下边两篇文章
参考文章1:https://www.cnblogs.com/mmnyjq/p/4065273.html
参考文章2:https://blog.csdn.net/qq_34231010/article/details/77923091