什么是多线程?为什么要使用多线程?
在介绍多线程之前,要介绍线程,但是不能介绍没有进程的线程。
首先,进程 :是一个正在执行的程序,每一个进程执行都有一个执行序列,是一个执行路径或者说是一个控制单元;
线程:是进程中一个独立的控制单元,线程在控制进程的执行。流程中至少有一个流程。
多线程:一个进程中有多个线程。
为什么使用多线程:
。为了更好地利用cpu资源,如果只有一个线程,第二个任务必须等到第一个任务结束。如果使用多线程,其他任务可以在主线程执行的同时执行,无需等待;
、进程不能共享数据,线程可以;
系统创建进程需要为该进程重新分配系统资源,因此创建线程的成本相对较小;
、java语言内置多线程支持,简化了Java多线程编程。
二、线程的生命周期:
New:从创建线程对象到程序start()的线程的状态是一个新的状态;
Ready:线程对象调用start()方法后,处于就绪状态,等待JVM中线程调度器的调度;
Run:就绪状态的线程在获得CPU资源后可以执行run(),然后线程处于运行状态,可以改变为就绪、阻塞、死三种状态。
等待/阻塞/休眠:一个线程执行sleep、suspend等方法后,会丢失其占用的资源,从而进入阻塞状态,休眠后可以重新进入就绪状态。
终止:run()方法完成或者其他终止条件发生后,会切换到终止状态。
三、创建线程的方法:具体实现代码详解请看点击后方链接:多线程扩展一、三种创建线程方法的详细比较(http://www.cnblogs.com/yjboke/p/8919090.html)
1、继承Thread类:
步骤:定义类继承线程;
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000。重写Thread类中的run方法;
目的:将自定义代码存储在run方法中,让线程运行。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000。调用线程的start方法:
这个方法有两步:启动线程,调用run方法。
\ 2、实现Runnable接口:接口应该由那些打算通过线程执行其实例的类来实现。一个类必须定义一个名为run的无参数方法。
实现步骤:定义一个类实现Runnable接口。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000。在Runnable接口中重写run方法。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000放入本次运行线程要运行的代码。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000。通过线程类建立线程对象。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000。将Runnable接口的子类对象作为实参传递给Thread类的构造函数。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \自定义run方法的对象是可运行的。因此,为了让线程执行指定对象的run方法,必须首先指定run方法所属的对象。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000。调用Thread类的start方法启动线程,调用Runnable接口子类的run方法。
3、通过Callable和Future创建线程:
实现步骤:创建一个可调用接口的实现类,实现call()方法。修改后的方法将被用作带有返回值的线程执行器。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000、创建可调用实现类的实例,使用FutureTask类封装可调用对象,FutureTask对象封装可调用对象的call()方法的返回值。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000、使用FutureTask对象作为线程对象启动一个新线程。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000调用FutureTask对象的get()方法获取子线程执行后的返回值。
第四,继承Thread类与实现Runnable接口和Callable接口的区别。
继承线程:线程代码存储在Thread子类的run方法中。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000优点:编写简单,不需要使用Thread.currentThread()方法,直接使用this.getname()就可以得到当前线程。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000缺点:Thread类已经被继承,其他类不能被继承。
实现Runnable:线程代码存储在接口子类的run方法中。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000优点:避免了单一继承的限制,多个线程可以共享一个目标对象,非常适合多线程处理同一个资源。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000缺点:比较复杂,访问线程必须使用Thread.currentThread()方法,没有返回值。
实现可调用:
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000优点:有返回值,避免了单一继承的限制,多个线程可以共享一个目标对象,非常适合多线程处理同一个资源。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000缺点:比较复杂,访问线程必须使用Thread.currentThread()方法。
建议通过实现接口来创建多线程。
动词(verb的缩写)线程状态管理
1、线程睡眠—sleep:
线程休眠的原因:线程执行太快,或者需要强制到下一个线程。
线程休眠方法(两种):sleep(long millis)使正在执行的线程在指定的毫秒数内休眠。
\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000
线程睡眠的代码演示:
public Syntest { public static void main(string[]args){ new thread(new count(),' countdown ')。start();} }类倒计时实现Runnable { int time=10public void run(){ while(true){ if(time=0){ system . out . println(thread . current thread()。getName()'' time-);试试{ thread . sleep(1000);//睡眠时间为1秒} catch(中断异常e){ e . printstacktrace();} } } } }
它将每秒打印一次,打印结果是:
倒计时:10: 9: 8: 7: 6: 5: 4: 3: 2: 1: 0
扩展:Java线程调度是Java多线程的核心。只有良好的调度才能充分发挥系统的性能,提高程序的执行效率。但是无论程序员怎么写调度,都只能最大限度地影响程序的执行顺序,而不能实现精确控制。因为使用sleep方法后,线程会进入阻塞状态,只有当睡眠时间结束后,才会重新进入就绪状态,就绪状态会进入运行状态,这是由系统控制的,我们无法准确的对其进行干预,所以如果我们调用Thread.sleep(1000)让线程睡眠1秒,结果可能会大于1秒。
2、线程让步—yield:
这个方法类似于sleep方法,也是Thread类提供的一个静态方法,可以让正在执行的线程暂停,但不是进入阻塞状态,而是直接进入就绪状态。这相当于暂停当前线程,然后重新进入就绪线程池,并让线程调度器再次重新调度它。还会有一个线程调用yield方法并暂停,但随后调度程序会调度它重新进入运行状态。
public class SynTest { public static void main(String[]args){ yield demo ms=new yield demo();线程t1=新线程(ms,'张三吃完就剩');线程t2=新线程(ms,'李四吃完就剩');线程t3=新线程(ms,'王五吃完就剩');t1 . start();T2 . start();T3 . start();} }class yieldDemo实现Runnable { int count=20public void run(){ while(true){ if(count 0){ system . out . println(thread . current thread()。getname () count-'瓜');if(count % 2==0){ thread . yield();\ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000 \ u 3000
\ \ u 3000 \ u 3000睡眠与产量的区别:
,sleep方法声明抛出InterruptedException,需要在调用此方法时捕获。Yield不声明异常,也不需要被捕获。
。sleep方法挂起当前线程后,会进入阻塞状态,只有到了睡眠时间,才会进入就绪状态。yield方法被调用后,直接进入就绪状态。
3、线程合并—join:
当线程B执行。join()方法,线程B将等待,直到线程A完成执行。
join可用于临时加入线程执行。
以下是代码演示:
public static void main(String[]args)抛出interrupted exception { yield demo ms=new yield demo();线程t1=新线程(ms,'张三吃完就剩');线程t2=新线程(ms,'李四吃完就剩');线程t3=新线程(ms,'王五吃完就剩');t1 . start();t1 . join();T2 . start();T3 . start();System.out.println('主线程');}
4、停止线程:
由于一个缺陷,原来的stop方法已经被停用,那么现在如何停止线程呢?现在分享一个,就是让run方法结束。
启动多线程,运行代码通常是循环结构,只要控制循环,run方法就可以结束。
渲染服务器搭建方案
055-79000是由趣皮条客娱乐开发的全新开放世界僵尸游戏,融合了第一人称射击、恐怖生存、塔防、角色扮演等元素。
这场战争不仅带来了无数的伤亡,也带来了一些不知名的病毒,让地球上的很多人类变成了僵尸。玩家将在美国亚利桑那州扮演一个幸存者的角色,这里是地球上最后一个未被污染的地方。玩家将一边为生存而战,一边探索整个事件背后的真相。
独立设置七日杀服务器。
《七杀》是一款开源游戏,你可以建立自己的专用服务器。
配置基本Linux服务器:
下载steamCMD:
开始配置七日杀戮服务器:
配置七日杀戮服务器的设置:
可能的服务器环境配置:
为服务器配置的交换:
检查安装SteamCmd运行所需的环境:
服务器镜像操作系统:Ubuntu 20 x64位系统。服务器推荐配置至少8核8G!
正版STEAM的七日必杀游戏
如果懒得设置用户,可以直接SU/SUDO启用超级管理员做所有操作(不推荐)。
服务器的选择:我个人推荐使用BGP line的服务器。
什么是BGP线路?你可能听过“北网通,南电信”这句话,字面意思。BGP线路是指电信、网通、移动三条线路合并成一个IP,不需要设置接口,自动分配最优网络线路。在稳定性和速度上更有优势,可以保证服务器的稳定运行。但是相比单线/双线,BGP成本会更高,不会出现网通平滑移动和网通平滑移动的情况。不需要接口。
此外,对于steam游戏如《泰尔》、《CSGO》、《方舟》等。游戏的帧数和渲染效果都很高。只有把显示效果和帧数做得更好,玩家才能有更好的游戏体验,所以服务器的CPU选择也很关键。对于高质量的画面游戏,支持睿频加速、多线程技术、动态加速频率的CPU会更适合,避免卡顿的情况。I9系列高频服务器挺合适的。
玩七杀的应该都知道服务器在海外,所以延迟会高。高延迟意味着游戏加载会很慢,这也是有些人会自建服务器的一个原因。个人搭建的服务器大多是国产服务器,延迟低,加载更快,游戏体验更好。
这就导致了一个问题。国内并不是所有机器都是低延迟的,还需要结合机房环境和服务器带宽。不同的机房,服务器的稳定性和安全性不同,带宽资源也不同。steam游戏帧数高占用带宽多,玩家数量多。如果带宽不足,延迟会更高。
上面提到steam游戏的帧数是相当高的。帧数越高,对服务器硬盘的配置要求就越高。现在市面上普遍使用SSD固态硬盘,运行速度很快。i9-9900K存储容量512G M.2固态硬盘。游戏行业同行竞争激烈,容易受到同行攻击,防御上可以根据自己的需求选择。
配置管理员密码:sudo passwd
进入超级用户模式并输入:su
sudo安装steamcmd
(如果有错误,找不到包steamcmd,请更新以下代码:)
首先,我需要将多元宇宙添加到我的/etc/apt/sources.list:
德布http://archive.ubuntu.com/ubuntu xenial主宇宙多元宇宙
黛比http://archive.ubuntu.com/ubuntu xenial-更新主宇宙多元宇宙
德布http://archive.ubuntu.com/ubuntu xenial-安全主宇宙多元宇宙
之后,添加i386架构:
sudo dpkg -添加-架构i386
最后apt-get更新就可以安装了。
sudo apt-get安装蒸汽cmd
更新代码:steamcmd
匿名登录用户:Steamlogin anonymous(不成功建议尝试steam用户登录)
Steam用户登录:登录帐户密码
#如果设置了安全令牌,将要求您输入一次安全令牌代码。
(可选)force _ install _ dir ~/7 daystodieserver #设置服务器端安装目录。
下载七日杀服务器端代码:app_update 294420
退出SteamCmd模式:退出
切换到根目录:cd~
打开。steam文件夹,并输入以下代码:
cd蒸汽应用程序/
Cd 7DaysToDieserver #这里是七日杀服务器的所有文件内容!
编辑七天Kill服务器配置文件:
Vim serverconfig.xml #编辑配置文件
* *按insert键或I键进入编辑模式**wq保存并退出!如果实在不行,可以用nano或者其他编辑器!
以下是XML文件的部分翻译,可以根据自己的需要进行修改。建议做个备份!注意:修改Value=!
可以通过浏览器搜索关于XML文件内容的官方维基百科内容3354。
property name=' servername value=' Jonas Lu/en/cn/fr/easy server name '/
property=' server port ' value=' 26900 '/#默认值是26900
property=' server password ' value='服务器登录密码'/
property=' server websiteurl ' value=' www . Jonas Lu . com '/服务器url
property=' servermaxplayercount ' value=' 8 '/#默认情况下,最大玩家数量为8
property=' server description ' value='关于服务器描述'/
属性名称='游戏世界'值=' Navezgane'/#服务器世界名称默认Navezgane
属性名='游戏名'值='我的游戏'/#存档名
属性='游戏难度'值=' 2'/#游戏难度
property=' Game mode ' value=' gamemodesurivalmp '/#游戏模式,默认gamemodesurivalmp
属性名='僵尸跑'值=' 0'/#僵尸走,默认值为0,白天走,晚上跑,1表示不跑,2表示一直跑。
property=' daynightlength ' value=' 60 '/#游戏内真实世界(三维)中一天的持续时间(单位分钟min)
属性='白昼长度'值=' 18'/#游戏中的时间(单位小时h)
属性name=' playerKillingmode ' value=' 1 '/#玩家之间可以造成的伤害,默认1。敌人0。无2。非联盟3。人人
property=' dropon death ' value=' 2 '/#当玩家死亡掉落时,默认为0。所有1。工具栏2。背包3。删除一切。
property=' maxspanedzombies ' value=' 60 '/#服务器的最大僵尸生成数
property=' maxspanedanimals ' value=' 50 '/#服务器的最大生物量
property=' airdrop frequency ' value=' 72 '/#空投周期的生成时间(单位分钟)
property name=' airdropmarker ' value=' true '/# airdrop是否默认为true?
如果你在这里实在看不懂或者觉得麻烦,可以下载下面JonasLu站长提供的编辑好的TXT文件,把后缀改成。xml并替换原来的XML文件!(注意改变文件中的服务器名称等。)
Serverconfig预配置的XML文件下载
该文件提供网页监控和到您的服务器的telnet连接。相关代码如下:
您的服务器的公共IP地址:8080
#例如,浏览器可以通过键入140.210.20.188: 8080来实时监控服务器日志。
Telnet您的服务器的公共IP地址是8081。
密码1234567890
#Telnet来连接和控制服务器
如果您发现服务器没有显示或无法连接,您可能还需要配置防火墙和端口规则。云请在相应平台的安全组页面添加入站和出站规则。如果没有特殊需要,可以全部放生!关闭防火墙!(有一定风险,不建议服务器中的重要信息!)
Web控制台(不需要,不要接通)
Telnet端口(这个不能释放,本地连接)
26900/26902
Telnet可以直接使用服务器中的telnet ip 8081登录,无需释放。
要通过远程登录进行连接,请在连接前在serverconfig.xml中设置TelnetPassword。
准备好上述文档后,在七天杀服务器的根目录下输入以下内容:
屏幕-S 7
#创建一个屏幕(防止服务器在ssh断开后自动关闭)。如果你没有,你可以下载!
下载屏幕:
# RedHat/CentOS
yum安装-y屏幕
–
# ubuntu/debian apt安装屏幕//我们在这里选择这段代码。/start server . sh-config file=server config . XML
#创建屏幕后,输入上面的代码正式启动服务器!
服务器成功启动后,按Ctrl A D将屏幕添加到后台!这不会关闭服务器。然后就可以开始玩了!
当您需要返回此页面时,请遵循以下说明。
Screen -ls #检查屏幕并记下数字7。
屏幕-r 7 #查看记录为7的数字
屏幕-r 7
# Ctrl C返回对应屏幕后!
#路径取决于您自己的安装位置。大致路径如下
~/./7DaysToDieServer #七天杀死服务器根目录
~/./7daystodieserver/data/worlds #七杀服务器地图目录
~/./.local/share/7daystodie/saves #七天查杀服务器存档目录(重要)
~/./7 daystodieserver/7 daystodieserver _ data #七天查杀服务器日志的输出目录
~/./7daystodieserver/mods # mods目录,需要自己创建。
~/./.local/share/7 days todie/Saves/server admin . XML
~/./7 daystodieserver/server config . XML #服务器配置文件
在服务器中安装telnet。(也可以使用Xshell或FTP远程连接)
# Ubuntu/Debian系统
Netstat -a | grep telnet #检测是否安装了telnet的rpm包。
O apt-get安装xinetd telnetd #如果没有,安装telnet。
Telnet您的8081 #登录服务器
管理玩家名称权限等级#给予玩家管理权限(最高等级为0)
管理玩家名称#移除玩家的管理权限。
管理玩家名字权限等级#提高管理权限等级
#建议先使用上述说明在telnet中给自己管理权限。
#然后在游戏中直接按F1就可以使用下面的指令了。
Dm #打开或关闭调试模式
禁止玩家名称时间#禁止玩家在一段时间内(分钟、小时、天、周、月、年)登录服务器
杀死指定的玩家
Listplayers lp #获取在线玩家信息
给出id/名称物品号#为玩家刷点东西
关机#关闭服务器
比方说#以服务器的名义广播消息。
linux系统的交换空间类似于windows系统的虚拟内存。如果你的云服务器内存小于4G,或者卡得很严重,那么你必须设置一个交换空间,否则服务器启动时会因为内存不足导致进程关闭而终止服务器。
Swapon命令可用于检查系统是否配置了swap。一般云服务器不会提前设置swap。
以下所有操作都在root //su中执行
Swapon -s #如果该命令没有返回结果,则意味着尚未为该系统配置swap。
Df -h #检查可用存储空间
如果没有,按如下方式创建交换文件。通常,建议将交换区的大小设置为其物理内存的两倍。我把8G设在这里。
#这些操作将在root用户中完成。
Sudo fallocate -l 8G /swapfile #请根据自身情况修改交换大小。
ls-LH/交换文件
Sudchmod600/swapfile #更改交换文件的权限,否则会有很大的安全隐患。
Ls -lh /swapfile #然后检查设置是否完成。
sudo mkswap /swapfile
sudo swapon /swapfile
#确保设置已经生效。
重新启动后,之前设置的交换将无效,通过修改fstab,配置将永久生效。
sudo vim /etc/fstab
按I进入输入模式,并在文件末尾添加下面一行。
/swapfile交换交换sw 0 0
按esc退出输入模式,输入:wq保存并退出。
Swappiness参数确定系统从内存交换数据到交换空间的频率。该值越接近0,系统就越倾向于在不交换的情况下最大限度地使用物理内存。值越接近100,越有可能使用swap,过多使用swap可能导致服务器运行效率变慢。ubuntu系统默认推荐值是60。这里为了保证服务器的运行效率,我建议设置为10。
Cat /proc/sys/vm/swappiness #查看当前交换性
Sudsysctl虚拟机。交换度=10 #将交换度修改为10
编辑sysctl配置文件,使其永久化。
sudo vim /etc/sysctl.conf
我按下进入输入模式,并将以下内容粘贴到文件的末尾:
vm.swappiness=10
按esc退出输入模式,输入:wq保存并退出。
#这些操作应该在root中完成。根据您的系统选择不同的说明。
# Ubuntu/Debian 64位
sudo apt -y安装lib32gcc1
# RedHat/CentOS 32位
sudo yum -y安装glibc libstdc
# RedHat/CentOS 64位
sudo yum -y安装glibc.i686 libstdc .i686